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_plugin.h ntru_plugin.c \
|
||||||
ntru_drbg.h ntru_drbg.c \
|
ntru_drbg.h ntru_drbg.c \
|
||||||
ntru_ke.h ntru_ke.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.h \
|
||||||
ntru_crypto/ntru_crypto_ntru_convert.c \
|
ntru_crypto/ntru_crypto_ntru_convert.c \
|
||||||
ntru_crypto/ntru_crypto_ntru_encrypt.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_key.c \
|
||||||
ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h \
|
ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h \
|
||||||
ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c \
|
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_mgftp1.h \
|
||||||
ntru_crypto/ntru_crypto_ntru_poly.h ntru_crypto/ntru_crypto_ntru_poly.c
|
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
|
libstrongswan_ntru_la_LDFLAGS = -module -avoid-version
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,6 @@
|
|||||||
#ifndef NTRU_CRYPTO_H
|
#ifndef NTRU_CRYPTO_H
|
||||||
#define NTRU_CRYPTO_H
|
#define NTRU_CRYPTO_H
|
||||||
|
|
||||||
#include "ntru_crypto_error.h"
|
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
#include "ntru_drbg.h"
|
#include "ntru_drbg.h"
|
||||||
@@ -88,10 +86,8 @@ typedef enum _NTRU_ENCRYPT_PARAM_SET_ID {
|
|||||||
#define NTRU_OUT_OF_MEMORY 8
|
#define NTRU_OUT_OF_MEMORY 8
|
||||||
#define NTRU_BAD_ENCODING 9
|
#define NTRU_BAD_ENCODING 9
|
||||||
#define NTRU_OID_NOT_RECOGNIZED 10
|
#define NTRU_OID_NOT_RECOGNIZED 10
|
||||||
|
#define NTRU_DRBG_FAIL 11
|
||||||
#define NTRU_RESULT(r) ((uint32_t)((r) ? NTRU_ERROR_BASE + (r) : (r)))
|
#define NTRU_MGF1_FAIL 12
|
||||||
#define NTRU_RET(r) return NTRU_RESULT((r))
|
|
||||||
|
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
|
|
||||||
@@ -116,18 +112,14 @@ typedef enum _NTRU_ENCRYPT_PARAM_SET_ID {
|
|||||||
* Upon return it is the actual size of the ciphertext.
|
* Upon return it is the actual size of the ciphertext.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* Returns NTRU_OK if successful.
|
||||||
* Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
|
* Returns NTRU_DRBG_FAIL if the DRBG handle is invalid.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
|
* Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL.
|
||||||
* (other than ct) is NULL.
|
* Returns NTRU_BAD_LENGTH if a length argument (pubkey_blob_len or pt_len) is
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
|
* zero, or if pt_len exceeds the maximum plaintext length for the parameter set.
|
||||||
* (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
|
* Returns NTRU_BAD_PUBLIC_KEY if the public-key blob is invalid
|
||||||
* maximum plaintext length for the parameter set.
|
* (unknown format, corrupt, bad length).
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
|
* Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small.
|
||||||
* invalid (unknown format, corrupt, bad length).
|
* Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
|
|
||||||
* is too small.
|
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
|
|
||||||
* allocated from the heap.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NTRUCALL
|
NTRUCALL
|
||||||
@@ -159,17 +151,14 @@ ntru_crypto_ntru_encrypt(
|
|||||||
* Upon return it is the actual size of the plaintext.
|
* Upon return it is the actual size of the plaintext.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* Returns NTRU_OK if successful.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
|
* Returns NTRU_BAD_PARAMETER if an argument pointer (other than pt) is NULL.
|
||||||
* (other than pt) is NULL.
|
* Returns NTRU_BAD_LENGTH if a length argument (privkey_blob) is zero, or if
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
|
* ct_len is invalid for the parameter set.
|
||||||
* (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
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
|
* (unknown format, corrupt, bad length).
|
||||||
* invalid (unknown format, corrupt, bad length).
|
* Returns NTRU_BUFFER_TOO_SMALL if the plaintext buffer is too small.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
|
* Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
|
||||||
* is too small.
|
* Returns NTRU_FAIL if a decryption error occurs.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
|
|
||||||
* allocated from the heap.
|
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NTRUCALL
|
NTRUCALL
|
||||||
@@ -193,7 +182,7 @@ ntru_crypto_ntru_decrypt(
|
|||||||
* instantiation the requested security strength must be at least as large
|
* instantiation the requested security strength must be at least as large
|
||||||
* as the security strength of the NTRU parameter set being used.
|
* as the security strength of the NTRU parameter set being used.
|
||||||
* Failure to instantiate the DRBG with the proper security strength will
|
* 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)
|
* The required minimum size of the output public-key buffer (pubkey_blob)
|
||||||
* may be queried by invoking this function with pubkey_blob = NULL.
|
* 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.
|
* and *privkey_blob_len is the actual size of the private-key blob.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* Returns NTRU_OK if successful.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
|
* Returns NTRU_BAD_PARAMETER if an argument pointer (other than pubkey_blob
|
||||||
* (other than pubkey_blob or privkey_blob) is NULL.
|
* or privkey_blob) is NULL.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
|
* Returns NTRU_INVALID_PARAMETER_SET if the parameter-set ID is invalid.
|
||||||
* ID is invalid.
|
* Returns NTRU_BAD_LENGTH if a length argument is invalid.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
|
* Returns NTRU_BUFFER_TOO_SMALL if either the pubkey_blob buffer or the
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
|
* privkey_blob buffer is too small.
|
||||||
* buffer or the privkey_blob buffer is too small.
|
* Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
|
* Returns NTRU_FAIL if the polynomial generated for f is not invertible in
|
||||||
* allocated from the heap.
|
* (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
|
|
||||||
* not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
|
|
||||||
* Should this occur, this function should simply be invoked again.
|
* 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_encrypt_key.h"
|
||||||
#include "ntru_crypto_ntru_convert.h"
|
#include "ntru_crypto_ntru_convert.h"
|
||||||
#include "ntru_crypto_ntru_poly.h"
|
#include "ntru_crypto_ntru_poly.h"
|
||||||
#include "ntru_crypto_ntru_mgf1.h"
|
#include "ntru_crypto_ntru_mgftp1.h"
|
||||||
|
|
||||||
/* ntru_crypto_ntru_encrypt
|
/* ntru_crypto_ntru_encrypt
|
||||||
*
|
*
|
||||||
@@ -63,18 +63,14 @@
|
|||||||
* Upon return it is the actual size of the ciphertext.
|
* Upon return it is the actual size of the ciphertext.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* Returns NTRU_OK if successful.
|
||||||
* Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
|
* Returns NTRU_DRBG_FAIL if the DRBG handle is invalid.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
|
* Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL.
|
||||||
* (other than ct) is NULL.
|
* Returns NTRU_BAD_LENGTH if a length argument (pubkey_blob_len or pt_len) is
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
|
* zero, or if pt_len exceeds the maximum plaintext length for the parameter set.
|
||||||
* (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
|
* Returns NTRU_BAD_PUBLIC_KEY if the public-key blob is invalid
|
||||||
* maximum plaintext length for the parameter set.
|
* (unknown format, corrupt, bad length).
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
|
* Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small.
|
||||||
* invalid (unknown format, corrupt, bad length).
|
* Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
|
|
||||||
* is too small.
|
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
|
|
||||||
* allocated from the heap.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
@@ -107,17 +103,20 @@ ntru_crypto_ntru_encrypt(
|
|||||||
uint8_t *tmp_buf = NULL;
|
uint8_t *tmp_buf = NULL;
|
||||||
bool msg_rep_good = FALSE;
|
bool msg_rep_good = FALSE;
|
||||||
hash_algorithm_t hash_algid;
|
hash_algorithm_t hash_algid;
|
||||||
uint8_t md_len;
|
|
||||||
uint16_t mprime_len = 0;
|
uint16_t mprime_len = 0;
|
||||||
uint16_t mod_q_mask;
|
uint16_t mod_q_mask;
|
||||||
uint32_t result = NTRU_OK;
|
uint32_t result = NTRU_OK;
|
||||||
|
|
||||||
/* check for bad parameters */
|
/* check for bad parameters */
|
||||||
|
|
||||||
if (!pubkey_blob || !pt || !ct_len)
|
if (!pubkey_blob || !pt || !ct_len)
|
||||||
NTRU_RET(NTRU_BAD_PARAMETER);
|
{
|
||||||
if ((pubkey_blob_len == 0) || (pt_len == 0))
|
return NTRU_BAD_PARAMETER;
|
||||||
NTRU_RET(NTRU_BAD_LENGTH);
|
}
|
||||||
|
if ((pubkey_blob_len == 0) || (pt_len == 0))
|
||||||
|
{
|
||||||
|
return NTRU_BAD_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
/* get a pointer to the parameter-set parameters, the packing type for
|
/* get a pointer to the parameter-set parameters, the packing type for
|
||||||
* the public key, and a pointer to the packed public key
|
* the public key, and a pointer to the packed public key
|
||||||
@@ -127,37 +126,45 @@ ntru_crypto_ntru_encrypt(
|
|||||||
pubkey_blob, &pubkey_pack_type,
|
pubkey_blob, &pubkey_pack_type,
|
||||||
NULL, ¶ms, &pubkey_packed,
|
NULL, ¶ms, &pubkey_packed,
|
||||||
NULL))
|
NULL))
|
||||||
NTRU_RET(NTRU_BAD_PUBLIC_KEY);
|
{
|
||||||
|
return NTRU_BAD_PUBLIC_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
/* return the ciphertext size if requested */
|
/* return the ciphertext size if requested */
|
||||||
|
|
||||||
packed_ct_len = (params->N * params->q_bits + 7) >> 3;
|
packed_ct_len = (params->N * params->q_bits + 7) >> 3;
|
||||||
if (!ct) {
|
if (!ct)
|
||||||
|
{
|
||||||
*ct_len = packed_ct_len;
|
*ct_len = packed_ct_len;
|
||||||
NTRU_RET(NTRU_OK);
|
return NTRU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the ciphertext buffer size */
|
/* check the ciphertext buffer size */
|
||||||
|
|
||||||
if (*ct_len < packed_ct_len) {
|
if (*ct_len < packed_ct_len)
|
||||||
NTRU_RET(NTRU_BUFFER_TOO_SMALL);
|
{
|
||||||
|
return NTRU_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the plaintext length */
|
/* check the plaintext length */
|
||||||
|
|
||||||
if (pt_len > params->m_len_max) {
|
if (pt_len > params->m_len_max)
|
||||||
NTRU_RET(NTRU_BAD_LENGTH);
|
{
|
||||||
|
return NTRU_BAD_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory for all operations */
|
/* 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 */
|
ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */
|
||||||
dr1 = params->dF_r & 0xff;
|
dr1 = params->dF_r & 0xff;
|
||||||
dr2 = (params->dF_r >> 8) & 0xff;
|
dr2 = (params->dF_r >> 8) & 0xff;
|
||||||
dr3 = (params->dF_r >> 16) & 0xff;
|
dr3 = (params->dF_r >> 16) & 0xff;
|
||||||
dr = dr1 + dr2 + dr3;
|
dr = dr1 + dr2 + dr3;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ring_mult_tmp_len = params->N; /* N 16-bit word buffer */
|
ring_mult_tmp_len = params->N; /* N 16-bit word buffer */
|
||||||
dr = params->dF_r;
|
dr = params->dF_r;
|
||||||
}
|
}
|
||||||
@@ -170,8 +177,9 @@ ntru_crypto_ntru_encrypt(
|
|||||||
params->sec_strength_len;
|
params->sec_strength_len;
|
||||||
/* buffer for b */
|
/* buffer for b */
|
||||||
scratch_buf = malloc(scratch_buf_len);
|
scratch_buf = malloc(scratch_buf_len);
|
||||||
if (!scratch_buf) {
|
if (!scratch_buf)
|
||||||
NTRU_RET(NTRU_OUT_OF_MEMORY);
|
{
|
||||||
|
return NTRU_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
ringel_buf = scratch_buf + ring_mult_tmp_len;
|
ringel_buf = scratch_buf + ring_mult_tmp_len;
|
||||||
r_buf = ringel_buf + params->N;
|
r_buf = ringel_buf + params->N;
|
||||||
@@ -179,20 +187,10 @@ ntru_crypto_ntru_encrypt(
|
|||||||
tmp_buf = (uint8_t *)scratch_buf;
|
tmp_buf = (uint8_t *)scratch_buf;
|
||||||
|
|
||||||
/* set hash algorithm based on security strength */
|
/* set hash algorithm based on security strength */
|
||||||
if (params->sec_strength_len <= 20)
|
hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256;
|
||||||
{
|
|
||||||
hash_algid = HASH_SHA1;
|
|
||||||
md_len = 20;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hash_algid = HASH_SHA256;
|
|
||||||
md_len = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set constants */
|
/* set constants */
|
||||||
|
mod_q_mask = params->q - 1;
|
||||||
mod_q_mask = params->q - 1;
|
|
||||||
|
|
||||||
/* loop until a message representative with proper weight is achieved */
|
/* loop until a message representative with proper weight is achieved */
|
||||||
|
|
||||||
@@ -210,10 +208,10 @@ ntru_crypto_ntru_encrypt(
|
|||||||
result = NTRU_FAIL;
|
result = NTRU_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
|
|
||||||
/* form sData (OID || m || b || hTrunc) */
|
/* form sData (OID || m || b || hTrunc) */
|
||||||
|
|
||||||
memcpy(ptr, params->OID, 3);
|
memcpy(ptr, params->OID, 3);
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
memcpy(ptr, pt, pt_len);
|
memcpy(ptr, pt, pt_len);
|
||||||
@@ -225,8 +223,7 @@ ntru_crypto_ntru_encrypt(
|
|||||||
|
|
||||||
|
|
||||||
/* generate r */
|
/* generate r */
|
||||||
|
result = ntru_gen_poly(hash_algid,
|
||||||
result = ntru_gen_poly(hash_algid, md_len,
|
|
||||||
params->min_IGF_hash_calls,
|
params->min_IGF_hash_calls,
|
||||||
(uint16_t)(ptr - tmp_buf),
|
(uint16_t)(ptr - tmp_buf),
|
||||||
tmp_buf, tmp_buf,
|
tmp_buf, tmp_buf,
|
||||||
@@ -236,11 +233,11 @@ ntru_crypto_ntru_encrypt(
|
|||||||
params->dF_r << 1, r_buf);
|
params->dF_r << 1, r_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
uint16_t pubkey_packed_len;
|
uint16_t pubkey_packed_len;
|
||||||
|
|
||||||
/* unpack the public key */
|
/* unpack the public key */
|
||||||
|
|
||||||
assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
|
assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
|
||||||
pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
|
pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
|
||||||
ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
|
ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
|
||||||
@@ -259,17 +256,15 @@ ntru_crypto_ntru_encrypt(
|
|||||||
scratch_buf, ringel_buf);
|
scratch_buf, ringel_buf);
|
||||||
|
|
||||||
/* form R mod 4 */
|
/* form R mod 4 */
|
||||||
|
|
||||||
ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf);
|
ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf);
|
||||||
|
|
||||||
/* form mask */
|
/* form mask */
|
||||||
|
result = ntru_mgftp1(hash_algid, params->min_MGF_hash_calls,
|
||||||
result = ntru_mgftp1(hash_algid, md_len,
|
|
||||||
params->min_MGF_hash_calls,
|
|
||||||
(params->N + 3) / 4, tmp_buf,
|
(params->N + 3) / 4, tmp_buf,
|
||||||
tmp_buf + params->N, params->N, 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 *Mtrin_buf = tmp_buf + params->N;
|
||||||
uint8_t *M_buf = Mtrin_buf + params->N -
|
uint8_t *M_buf = Mtrin_buf + params->N -
|
||||||
(params->sec_strength_len + params->m_len_len +
|
(params->sec_strength_len + params->m_len_len +
|
||||||
@@ -277,7 +272,6 @@ ntru_crypto_ntru_encrypt(
|
|||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
/* form the padded message M */
|
/* form the padded message M */
|
||||||
|
|
||||||
ptr = M_buf;
|
ptr = M_buf;
|
||||||
memcpy(ptr, b_buf, params->sec_strength_len);
|
memcpy(ptr, b_buf, params->sec_strength_len);
|
||||||
ptr += 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);
|
memset(ptr, 0, params->m_len_max - pt_len + 2);
|
||||||
|
|
||||||
/* convert M to trits (Mbin to Mtrin) */
|
/* convert M to trits (Mbin to Mtrin) */
|
||||||
|
|
||||||
mprime_len = params->N;
|
mprime_len = params->N;
|
||||||
if (params->is_product_form)
|
if (params->is_product_form)
|
||||||
|
{
|
||||||
--mprime_len;
|
--mprime_len;
|
||||||
|
}
|
||||||
|
|
||||||
ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf);
|
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);
|
} while ((result == NTRU_OK) && !msg_rep_good);
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
/* form ciphertext e by adding m' to R mod q */
|
/* 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;
|
ringel_buf[i] = (ringel_buf[i] - m1) & mod_q_mask;
|
||||||
|
|
||||||
/* pack ciphertext */
|
/* pack ciphertext */
|
||||||
|
|
||||||
ntru_elements_2_octets(params->N, ringel_buf, params->q_bits, ct);
|
ntru_elements_2_octets(params->N, ringel_buf, params->q_bits, ct);
|
||||||
*ct_len = packed_ct_len;
|
*ct_len = packed_ct_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
|
|
||||||
memset(scratch_buf, 0, scratch_buf_len);
|
memset(scratch_buf, 0, scratch_buf_len);
|
||||||
free(scratch_buf);
|
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.
|
* Upon return it is the actual size of the plaintext.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* Returns NTRU_OK if successful.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
|
* Returns NTRU_BAD_PARAMETER if an argument pointer (other than pt) is NULL.
|
||||||
* (other than pt) is NULL.
|
* Returns NTRU_BAD_LENGTH if a length argument (privkey_blob) is zero, or if
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
|
* ct_len is invalid for the parameter set.
|
||||||
* (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
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
|
* (unknown format, corrupt, bad length).
|
||||||
* invalid (unknown format, corrupt, bad length).
|
* Returns NTRU_BUFFER_TOO_SMALL if the plaintext buffer is too small.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
|
* Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
|
||||||
* is too small.
|
* Returns NTRU_FAIL if a decryption error occurs.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
|
|
||||||
* allocated from the heap.
|
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
@@ -427,7 +418,6 @@ ntru_crypto_ntru_decrypt(
|
|||||||
uint8_t *M_buf = NULL;
|
uint8_t *M_buf = NULL;
|
||||||
uint8_t *ptr = NULL;
|
uint8_t *ptr = NULL;
|
||||||
hash_algorithm_t hash_algid;
|
hash_algorithm_t hash_algid;
|
||||||
uint8_t md_len;
|
|
||||||
uint16_t cmprime_len;
|
uint16_t cmprime_len;
|
||||||
uint16_t mod_q_mask;
|
uint16_t mod_q_mask;
|
||||||
uint16_t q_mod_p;
|
uint16_t q_mod_p;
|
||||||
@@ -439,28 +429,35 @@ ntru_crypto_ntru_decrypt(
|
|||||||
|
|
||||||
/* check for bad parameters */
|
/* check for bad parameters */
|
||||||
|
|
||||||
if (!privkey_blob || !ct || !pt_len)
|
if (!privkey_blob || !ct || !pt_len)
|
||||||
NTRU_RET(NTRU_BAD_PARAMETER);
|
{
|
||||||
if ((privkey_blob_len == 0) || (ct_len == 0))
|
return NTRU_BAD_PARAMETER;
|
||||||
NTRU_RET(NTRU_BAD_LENGTH);
|
}
|
||||||
|
if ((privkey_blob_len == 0) || (ct_len == 0))
|
||||||
|
{
|
||||||
|
return NTRU_BAD_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
/* get a pointer to the parameter-set parameters, the packing types for
|
/* get a pointer to the parameter-set parameters, the packing types for
|
||||||
* the public and private keys, and pointers to the packed public and
|
* the public and private keys, and pointers to the packed public and
|
||||||
* private keys
|
* 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_len,
|
||||||
privkey_blob, &pubkey_pack_type,
|
privkey_blob, &pubkey_pack_type,
|
||||||
&privkey_pack_type, ¶ms,
|
&privkey_pack_type, ¶ms,
|
||||||
&pubkey_packed, &privkey_packed))
|
&pubkey_packed, &privkey_packed))
|
||||||
NTRU_RET(NTRU_BAD_PRIVATE_KEY);
|
{
|
||||||
|
return NTRU_BAD_PRIVATE_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
/* return the max plaintext size if requested */
|
/* return the max plaintext size if requested */
|
||||||
|
|
||||||
if (!pt) {
|
if (!pt)
|
||||||
|
{
|
||||||
*pt_len = params->m_len_max;
|
*pt_len = params->m_len_max;
|
||||||
NTRU_RET(NTRU_OK);
|
return NTRU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cannot check the plaintext buffer size until after the plaintext
|
/* cannot check the plaintext buffer size until after the plaintext
|
||||||
@@ -470,12 +467,15 @@ ntru_crypto_ntru_decrypt(
|
|||||||
|
|
||||||
/* check the ciphertext length */
|
/* check the ciphertext length */
|
||||||
|
|
||||||
if (ct_len != (params->N * params->q_bits + 7) >> 3)
|
if (ct_len != (params->N * params->q_bits + 7) >> 3)
|
||||||
NTRU_RET(NTRU_BAD_LENGTH);
|
{
|
||||||
|
return NTRU_BAD_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate memory for all operations */
|
/* 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 */
|
ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */
|
||||||
dF_r1 = params->dF_r & 0xff;
|
dF_r1 = params->dF_r & 0xff;
|
||||||
dF_r2 = (params->dF_r >> 8) & 0xff;
|
dF_r2 = (params->dF_r >> 8) & 0xff;
|
||||||
@@ -493,8 +493,9 @@ ntru_crypto_ntru_decrypt(
|
|||||||
(dF_r << 2) + /* buffer for F, r indices */
|
(dF_r << 2) + /* buffer for F, r indices */
|
||||||
params->m_len_max; /* buffer for plaintext */
|
params->m_len_max; /* buffer for plaintext */
|
||||||
scratch_buf = malloc(scratch_buf_len);
|
scratch_buf = malloc(scratch_buf_len);
|
||||||
if (!scratch_buf) {
|
if (!scratch_buf)
|
||||||
NTRU_RET(NTRU_OUT_OF_MEMORY);
|
{
|
||||||
|
return NTRU_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
ringel_buf1 = scratch_buf + ring_mult_tmp_len;
|
ringel_buf1 = scratch_buf + ring_mult_tmp_len;
|
||||||
ringel_buf2 = ringel_buf1 + params->N;
|
ringel_buf2 = ringel_buf1 + params->N;
|
||||||
@@ -505,38 +506,31 @@ ntru_crypto_ntru_decrypt(
|
|||||||
M_buf = Mtrin_buf + params->N;
|
M_buf = Mtrin_buf + params->N;
|
||||||
|
|
||||||
/* set hash algorithm based on security strength */
|
/* set hash algorithm based on security strength */
|
||||||
if (params->sec_strength_len <= 20)
|
hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256;
|
||||||
{
|
|
||||||
hash_algid = HASH_SHA1;
|
|
||||||
md_len = 20;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hash_algid = HASH_SHA256;
|
|
||||||
md_len = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set constants */
|
/* set constants */
|
||||||
|
|
||||||
mod_q_mask = params->q - 1;
|
mod_q_mask = params->q - 1;
|
||||||
q_mod_p = params->q % 3;
|
q_mod_p = params->q % 3;
|
||||||
|
|
||||||
/* unpack the ciphertext */
|
/* unpack the ciphertext */
|
||||||
|
|
||||||
ntru_octets_2_elements(ct_len, ct, params->q_bits, ringel_buf2);
|
ntru_octets_2_elements(ct_len, ct, params->q_bits, ringel_buf2);
|
||||||
|
|
||||||
/* unpack the private key */
|
/* 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,
|
ntru_packed_trits_2_indices(privkey_packed, params->N, i_buf,
|
||||||
i_buf + dF_r);
|
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(
|
ntru_octets_2_elements(
|
||||||
(((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3,
|
(((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3,
|
||||||
privkey_packed, params->N_bits, i_buf);
|
privkey_packed, params->N_bits, i_buf);
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
assert(FALSE);
|
assert(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,7 +542,8 @@ ntru_crypto_ntru_decrypt(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
cmprime_len = params->N;
|
cmprime_len = params->N;
|
||||||
if (params->is_product_form) {
|
if (params->is_product_form)
|
||||||
|
{
|
||||||
--cmprime_len;
|
--cmprime_len;
|
||||||
ntru_ring_mult_product_indices(ringel_buf2, (uint16_t)dF_r1,
|
ntru_ring_mult_product_indices(ringel_buf2, (uint16_t)dF_r1,
|
||||||
(uint16_t)dF_r2, (uint16_t)dF_r3,
|
(uint16_t)dF_r2, (uint16_t)dF_r3,
|
||||||
@@ -564,7 +559,9 @@ ntru_crypto_ntru_decrypt(
|
|||||||
else if (Mtrin_buf[i] == 2)
|
else if (Mtrin_buf[i] == 2)
|
||||||
--m1;
|
--m1;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ntru_ring_mult_indices(ringel_buf2, (uint16_t)dF_r, (uint16_t)dF_r,
|
ntru_ring_mult_indices(ringel_buf2, (uint16_t)dF_r, (uint16_t)dF_r,
|
||||||
i_buf, params->N, params->q,
|
i_buf, params->N, params->q,
|
||||||
scratch_buf, ringel_buf1);
|
scratch_buf, ringel_buf1);
|
||||||
@@ -581,11 +578,15 @@ ntru_crypto_ntru_decrypt(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (params->is_product_form)
|
if (params->is_product_form)
|
||||||
decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) :
|
{
|
||||||
(bool)( m1 <= params->min_msg_rep_wt);
|
decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) :
|
||||||
else
|
(bool)( m1 <= params->min_msg_rep_wt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf,
|
decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf,
|
||||||
params->min_msg_rep_wt);
|
params->min_msg_rep_wt);
|
||||||
|
}
|
||||||
|
|
||||||
/* form cR = e - cm' mod q */
|
/* form cR = e - cm' mod q */
|
||||||
|
|
||||||
@@ -605,12 +606,12 @@ ntru_crypto_ntru_decrypt(
|
|||||||
|
|
||||||
/* form mask */
|
/* form mask */
|
||||||
|
|
||||||
result = ntru_mgftp1(hash_algid, md_len,
|
result = ntru_mgftp1(hash_algid, params->min_MGF_hash_calls,
|
||||||
params->min_MGF_hash_calls,
|
|
||||||
(params->N + 3) / 4, tmp_buf,
|
(params->N + 3) / 4, tmp_buf,
|
||||||
tmp_buf + params->N, params->N, 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 */
|
/* form cMtrin by subtracting mask from cm', mod p */
|
||||||
|
|
||||||
@@ -665,7 +666,7 @@ ntru_crypto_ntru_decrypt(
|
|||||||
|
|
||||||
/* generate cr */
|
/* generate cr */
|
||||||
|
|
||||||
result = ntru_gen_poly(hash_algid, md_len,
|
result = ntru_gen_poly(hash_algid,
|
||||||
params->min_IGF_hash_calls,
|
params->min_IGF_hash_calls,
|
||||||
(uint16_t)(ptr - tmp_buf),
|
(uint16_t)(ptr - tmp_buf),
|
||||||
tmp_buf, tmp_buf,
|
tmp_buf, tmp_buf,
|
||||||
@@ -675,7 +676,8 @@ ntru_crypto_ntru_decrypt(
|
|||||||
params->dF_r << 1, i_buf);
|
params->dF_r << 1, i_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
|
|
||||||
/* unpack the public key */
|
/* unpack the public key */
|
||||||
|
|
||||||
@@ -709,9 +711,12 @@ ntru_crypto_ntru_decrypt(
|
|||||||
|
|
||||||
/* output plaintext and plaintext length */
|
/* output plaintext and plaintext length */
|
||||||
|
|
||||||
if (decryption_ok) {
|
if (decryption_ok)
|
||||||
|
{
|
||||||
if (*pt_len < cm_len)
|
if (*pt_len < cm_len)
|
||||||
NTRU_RET(NTRU_BUFFER_TOO_SMALL);
|
{
|
||||||
|
return NTRU_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
memcpy(pt, m_buf, cm_len);
|
memcpy(pt, m_buf, cm_len);
|
||||||
*pt_len = cm_len;
|
*pt_len = cm_len;
|
||||||
}
|
}
|
||||||
@@ -723,8 +728,11 @@ ntru_crypto_ntru_decrypt(
|
|||||||
free(scratch_buf);
|
free(scratch_buf);
|
||||||
|
|
||||||
if (!decryption_ok)
|
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.
|
* 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)
|
* The required minimum size of the output public-key buffer (pubkey_blob)
|
||||||
* may be queried by invoking this function with pubkey_blob = NULL.
|
* may be queried by invoking this function with pubkey_blob = NULL.
|
||||||
* In this case, no key generation is performed, NTRU_OK is returned, and
|
* 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.
|
* and *privkey_blob_len is the actual size of the private-key blob.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* Returns NTRU_OK if successful.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
|
* Returns NTRU_BAD_PARAMETER if an argument pointer (other than pubkey_blob or
|
||||||
* (other than pubkey_blob or privkey_blob) is NULL.
|
* privkey_blob) is NULL.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
|
* Returns NTRU_INVALID_PARAMETER_SET if the parameter-set ID is invalid.
|
||||||
* ID is invalid.
|
* Returns NTRU_BAD_LENGTH if a length argument is invalid.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
|
* Returns NTRU_BUFFER_TOO_SMALL if either the pubkey_blob buffer or the
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
|
* privkey_blob buffer is too small.
|
||||||
* buffer or the privkey_blob buffer is too small.
|
* Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
|
* Returns NTRU_FAIL if the polynomial generated for f is not invertible in
|
||||||
* allocated from the heap.
|
* (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
|
||||||
* Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
|
|
||||||
* not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
|
|
||||||
* Should this occur, this function should simply be invoked again.
|
* 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 */
|
/* get a pointer to the parameter-set parameters */
|
||||||
|
|
||||||
if ((params = ntru_encrypt_get_params_with_id(param_set_id)) == NULL)
|
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 */
|
/* check for bad parameters */
|
||||||
|
|
||||||
if (!pubkey_blob_len || !privkey_blob_len)
|
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 */
|
/* 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 */
|
/* 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)
|
if (!pubkey_blob)
|
||||||
*pubkey_blob_len = public_key_blob_len;
|
*pubkey_blob_len = public_key_blob_len;
|
||||||
if (!privkey_blob)
|
if (!privkey_blob)
|
||||||
*privkey_blob_len = private_key_blob_len;
|
*privkey_blob_len = private_key_blob_len;
|
||||||
NTRU_RET(NTRU_OK);
|
return NTRU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check size of output buffers */
|
/* check size of output buffers */
|
||||||
|
|
||||||
if ((*pubkey_blob_len < public_key_blob_len) ||
|
if ((*pubkey_blob_len < public_key_blob_len) ||
|
||||||
(*privkey_blob_len < private_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 */
|
/* allocate memory for all operations */
|
||||||
|
|
||||||
if (params->is_product_form) {
|
if (params->is_product_form) {
|
||||||
dF1 = params->dF_r & 0xff;
|
dF1 = params->dF_r & 0xff;
|
||||||
dF2 = (params->dF_r >> 8) & 0xff;
|
dF2 = (params->dF_r >> 8) & 0xff;
|
||||||
@@ -862,8 +867,9 @@ ntru_crypto_ntru_encrypt_keygen(
|
|||||||
2N-byte buffer for f^-1 */
|
2N-byte buffer for f^-1 */
|
||||||
(dF << 2); /* buffer for F indices */
|
(dF << 2); /* buffer for F indices */
|
||||||
scratch_buf = malloc(scratch_buf_len);
|
scratch_buf = malloc(scratch_buf_len);
|
||||||
if (!scratch_buf) {
|
if (!scratch_buf)
|
||||||
NTRU_RET(NTRU_OUT_OF_MEMORY);
|
{
|
||||||
|
return NTRU_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
ringel_buf1 = scratch_buf + (params->N << 1);
|
ringel_buf1 = scratch_buf + (params->N << 1);
|
||||||
ringel_buf2 = ringel_buf1 + params->N;
|
ringel_buf2 = ringel_buf1 + params->N;
|
||||||
@@ -897,14 +903,14 @@ ntru_crypto_ntru_encrypt_keygen(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = NTRU_FAIL;
|
result = NTRU_DRBG_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
|
|
||||||
/* generate F */
|
/* generate F */
|
||||||
|
result = ntru_gen_poly(hash_algid,
|
||||||
result = ntru_gen_poly(hash_algid, md_len,
|
|
||||||
params->min_IGF_hash_calls,
|
params->min_IGF_hash_calls,
|
||||||
seed_len, tmp_buf, tmp_buf,
|
seed_len, tmp_buf, tmp_buf,
|
||||||
params->N, params->c_bits,
|
params->N, params->c_bits,
|
||||||
@@ -913,7 +919,8 @@ ntru_crypto_ntru_encrypt_keygen(
|
|||||||
params->dF_r << 1, F_buf);
|
params->dF_r << 1, F_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
memset(ringel_buf1, 0, params->N * sizeof(uint16_t));
|
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,
|
if (!ntru_ring_inv(ringel_buf1, params->N, params->q,
|
||||||
scratch_buf, ringel_buf2))
|
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
|
/* get random bytes for seed for generating trinary g
|
||||||
* as a list of indices
|
* 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,
|
if (!drbg->generate(drbg, params->sec_strength_len << 3, seed_len,
|
||||||
tmp_buf))
|
tmp_buf))
|
||||||
{
|
{
|
||||||
result = NTRU_FAIL;
|
result = NTRU_DRBG_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
uint16_t min_IGF_hash_calls =
|
uint16_t min_IGF_hash_calls =
|
||||||
((((params->dg << 2) + 2) * params->N_bits) + (md_len << 3) - 1) /
|
((((params->dg << 2) + 2) * params->N_bits) + (md_len << 3) - 1) /
|
||||||
(md_len << 3);
|
(md_len << 3);
|
||||||
|
|
||||||
/* generate g */
|
/* generate g */
|
||||||
|
|
||||||
result = ntru_gen_poly(hash_algid, md_len,
|
result = ntru_gen_poly(hash_algid,
|
||||||
(uint8_t)min_IGF_hash_calls,
|
(uint8_t)min_IGF_hash_calls,
|
||||||
seed_len, tmp_buf, tmp_buf,
|
seed_len, tmp_buf, tmp_buf,
|
||||||
params->N, params->c_bits,
|
params->N, params->c_bits,
|
||||||
@@ -997,7 +1008,8 @@ ntru_crypto_ntru_encrypt_keygen(
|
|||||||
(params->dg << 1) + 1, ringel_buf1);
|
(params->dg << 1) + 1, ringel_buf1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NTRU_OK) {
|
if (result == NTRU_OK)
|
||||||
|
{
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
/* compute h = p * (f^-1 * g) mod q */
|
/* compute h = p * (f^-1 * g) mod q */
|
||||||
|
|||||||
+38
-106
@@ -2,7 +2,7 @@
|
|||||||
* NTRU Cryptography Reference Source Code
|
* NTRU Cryptography Reference Source Code
|
||||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
* 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
|
* 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 <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include "ntru_crypto_ntru_mgftp1.h"
|
||||||
#include "ntru_crypto_ntru_mgf1.h"
|
|
||||||
#include "ntru_crypto_ntru_convert.h"
|
#include "ntru_crypto_ntru_convert.h"
|
||||||
|
|
||||||
|
#include "ntru_mgf1.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ntru_mgftp1
|
/* ntru_mgftp1
|
||||||
*
|
*
|
||||||
@@ -122,7 +48,7 @@ ntru_mgf1(
|
|||||||
* The state (string and counter) is initialized when a seed is present.
|
* The state (string and counter) is initialized when a seed is present.
|
||||||
*
|
*
|
||||||
* Returns NTRU_OK if successful.
|
* 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(
|
ntru_mgftp1(
|
||||||
hash_algorithm_t hash_algid, /* in - hash alg ID for
|
hash_algorithm_t hash_algid, /* in - hash alg ID for
|
||||||
MGF-TP-1 */
|
MGF-TP-1 */
|
||||||
uint8_t md_len, /* in - no. of octets in
|
|
||||||
digest */
|
|
||||||
uint8_t min_calls, /* in - minimum no. of hash
|
uint8_t min_calls, /* in - minimum no. of hash
|
||||||
calls */
|
calls */
|
||||||
uint16_t seed_len, /* in - no. of octets in seed */
|
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 */
|
uint16_t num_trits_needed, /* in - no. of trits in mask */
|
||||||
uint8_t *mask) /* out - address for mask trits */
|
uint8_t *mask) /* out - address for mask trits */
|
||||||
{
|
{
|
||||||
uint8_t *mgf_out;
|
uint8_t md_len;
|
||||||
uint8_t *octets;
|
uint8_t *octets;
|
||||||
uint16_t octets_available;
|
uint16_t octets_available;
|
||||||
uint32_t retcode;
|
ntru_mgf1_t *mgf1;
|
||||||
|
|
||||||
assert(seed);
|
|
||||||
assert(buf);
|
|
||||||
assert(mask);
|
|
||||||
|
|
||||||
/* generate minimum MGF1 output */
|
/* generate minimum MGF1 output */
|
||||||
mgf_out = buf + md_len + 4;
|
mgf1 = ntru_mgf1_create(hash_algid, chunk_create(seed, seed_len), TRUE);
|
||||||
if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
|
if (!mgf1)
|
||||||
seed_len, seed, mgf_out)) != NTRU_OK)
|
|
||||||
{
|
{
|
||||||
return retcode;
|
return NTRU_MGF1_FAIL;
|
||||||
}
|
}
|
||||||
octets = mgf_out;
|
md_len = mgf1->get_hash_size(mgf1);
|
||||||
|
octets = buf;
|
||||||
octets_available = min_calls * md_len;
|
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 */
|
/* get trits for mask */
|
||||||
while (num_trits_needed >= 5)
|
while (num_trits_needed >= 5)
|
||||||
{
|
{
|
||||||
/* get another octet and convert it to 5 trits */
|
/* get another octet and convert it to 5 trits */
|
||||||
if (octets_available == 0)
|
if (octets_available == 0)
|
||||||
{
|
{
|
||||||
if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
|
octets = buf;
|
||||||
0, NULL, mgf_out)) != NTRU_OK)
|
|
||||||
{
|
|
||||||
return retcode;
|
|
||||||
}
|
|
||||||
octets = mgf_out;
|
|
||||||
octets_available = md_len;
|
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)
|
if (*octets < 243)
|
||||||
@@ -193,13 +122,15 @@ ntru_mgftp1(
|
|||||||
/* get another octet and convert it to remaining trits */
|
/* get another octet and convert it to remaining trits */
|
||||||
if (octets_available == 0)
|
if (octets_available == 0)
|
||||||
{
|
{
|
||||||
if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
|
octets = buf;
|
||||||
0, NULL, mgf_out)) != NTRU_OK)
|
|
||||||
{
|
|
||||||
return retcode;
|
|
||||||
}
|
|
||||||
octets = mgf_out;
|
|
||||||
octets_available = md_len;
|
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)
|
if (*octets < 243)
|
||||||
{
|
{
|
||||||
@@ -213,8 +144,9 @@ ntru_mgftp1(
|
|||||||
--octets_available;
|
--octets_available;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mgf1->destroy(mgf1);
|
||||||
|
|
||||||
NTRU_RET(NTRU_OK);
|
return NTRU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+3
-31
@@ -2,7 +2,7 @@
|
|||||||
* NTRU Cryptography Reference Source Code
|
* NTRU Cryptography Reference Source Code
|
||||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
* 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
|
* 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>
|
#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
|
/* ntru_mgftp1
|
||||||
*
|
*
|
||||||
* Implements a mask-generation function for trinary polynomials,
|
* Implements a mask-generation function for trinary polynomials,
|
||||||
@@ -83,8 +57,6 @@ extern uint32_t
|
|||||||
ntru_mgftp1(
|
ntru_mgftp1(
|
||||||
hash_algorithm_t hash_algid, /* in - hash alg ID for
|
hash_algorithm_t hash_algid, /* in - hash alg ID for
|
||||||
MGF-TP-1 */
|
MGF-TP-1 */
|
||||||
uint8_t md_len, /* in - no. of octets in
|
|
||||||
digest */
|
|
||||||
uint8_t min_calls, /* in - minimum no. of hash
|
uint8_t min_calls, /* in - minimum no. of hash
|
||||||
calls */
|
calls */
|
||||||
uint16_t seed_len, /* in - no. of octets in seed */
|
uint16_t seed_len, /* in - no. of octets in seed */
|
||||||
@@ -34,10 +34,12 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
#include "ntru_crypto_ntru_poly.h"
|
#include "ntru_crypto_ntru_poly.h"
|
||||||
#include "ntru_crypto_ntru_mgf1.h"
|
#include "ntru_crypto_ntru_mgftp1.h"
|
||||||
|
|
||||||
|
#include "ntru_mgf1.h"
|
||||||
|
|
||||||
|
#include <utils/debug.h>
|
||||||
|
|
||||||
/* ntru_gen_poly
|
/* ntru_gen_poly
|
||||||
*
|
*
|
||||||
@@ -64,7 +66,6 @@ uint32_t
|
|||||||
ntru_gen_poly(
|
ntru_gen_poly(
|
||||||
hash_algorithm_t hash_algid, /* in - hash algorithm ID for
|
hash_algorithm_t hash_algid, /* in - hash algorithm ID for
|
||||||
IGF-2 */
|
IGF-2 */
|
||||||
uint8_t md_len, /* in - no. of octets in digest */
|
|
||||||
uint8_t min_calls, /* in - minimum no. of hash
|
uint8_t min_calls, /* in - minimum no. of hash
|
||||||
calls */
|
calls */
|
||||||
uint16_t seed_len, /* in - no. of octets in seed */
|
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 */
|
uint32_t indices_counts, /* in - nos. of indices needed */
|
||||||
uint16_t *indices) /* out - address for indices */
|
uint16_t *indices) /* out - address for indices */
|
||||||
{
|
{
|
||||||
uint8_t *mgf_out;
|
uint8_t md_len;
|
||||||
uint8_t *octets;
|
uint8_t *octets;
|
||||||
uint8_t *used;
|
uint8_t *used;
|
||||||
uint8_t num_polys;
|
uint8_t num_polys;
|
||||||
@@ -89,23 +90,26 @@ ntru_gen_poly(
|
|||||||
uint16_t index_cnt = 0;
|
uint16_t index_cnt = 0;
|
||||||
uint8_t left = 0;
|
uint8_t left = 0;
|
||||||
uint8_t num_left = 0;
|
uint8_t num_left = 0;
|
||||||
uint32_t retcode;
|
ntru_mgf1_t *mgf1;
|
||||||
|
|
||||||
assert(seed);
|
|
||||||
assert(buf);
|
|
||||||
assert(indices);
|
|
||||||
|
|
||||||
/* generate minimum MGF1 output */
|
/* generate minimum MGF1 output */
|
||||||
|
mgf1 = ntru_mgf1_create(hash_algid, chunk_create(seed, seed_len), TRUE);
|
||||||
mgf_out = buf + md_len + 4;
|
if (!mgf1)
|
||||||
if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
|
{
|
||||||
seed_len, seed, mgf_out)) != NTRU_OK)
|
return NTRU_MGF1_FAIL;
|
||||||
return retcode;
|
}
|
||||||
octets = mgf_out;
|
md_len = mgf1->get_hash_size(mgf1);
|
||||||
|
octets = buf;
|
||||||
octets_available = min_calls * md_len;
|
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) {
|
if (is_product_form) {
|
||||||
|
|
||||||
/* number of indices for poly1 is in low byte of indices_counts,
|
/* number of indices for poly1 is in low byte of indices_counts,
|
||||||
@@ -126,7 +130,7 @@ ntru_gen_poly(
|
|||||||
|
|
||||||
/* init used-index array */
|
/* init used-index array */
|
||||||
|
|
||||||
used = mgf_out + octets_available;
|
used = buf + octets_available;
|
||||||
memset(used, 0, N);
|
memset(used, 0, N);
|
||||||
|
|
||||||
/* generate indices (IGF-2) for all polynomials */
|
/* generate indices (IGF-2) for all polynomials */
|
||||||
@@ -153,21 +157,28 @@ ntru_gen_poly(
|
|||||||
/* get the rest of the bits needed from new octets */
|
/* get the rest of the bits needed from new octets */
|
||||||
|
|
||||||
num_needed = c_bits - num_left;
|
num_needed = c_bits - num_left;
|
||||||
while (num_needed != 0) {
|
while (num_needed != 0)
|
||||||
|
{
|
||||||
|
|
||||||
/* get another octet */
|
/* get another octet */
|
||||||
|
if (octets_available == 0)
|
||||||
if (octets_available == 0) {
|
{
|
||||||
if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
|
octets = buf;
|
||||||
0, NULL, mgf_out)) != NTRU_OK)
|
|
||||||
return retcode;
|
|
||||||
octets = mgf_out;
|
|
||||||
octets_available = md_len;
|
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++;
|
left = *octets++;
|
||||||
--octets_available;
|
--octets_available;
|
||||||
|
|
||||||
if (num_needed <= 8) {
|
if (num_needed <= 8)
|
||||||
|
{
|
||||||
|
|
||||||
/* all bits needed to fill the index are in this octet */
|
/* all bits needed to fill the index are in this octet */
|
||||||
|
|
||||||
@@ -191,7 +202,8 @@ ntru_gen_poly(
|
|||||||
/* form index and check if unique */
|
/* form index and check if unique */
|
||||||
|
|
||||||
index %= N;
|
index %= N;
|
||||||
if (!used[index]) {
|
if (!used[index])
|
||||||
|
{
|
||||||
used[index] = 1;
|
used[index] = 1;
|
||||||
indices[index_cnt] = index;
|
indices[index_cnt] = index;
|
||||||
++index_cnt;
|
++index_cnt;
|
||||||
@@ -201,15 +213,17 @@ ntru_gen_poly(
|
|||||||
|
|
||||||
/* init for next polynomial if another polynomial to be generated */
|
/* init for next polynomial if another polynomial to be generated */
|
||||||
|
|
||||||
if (num_polys > 0) {
|
if (num_polys > 0)
|
||||||
|
{
|
||||||
memset(used, 0, N);
|
memset(used, 0, N);
|
||||||
num_indices = num_indices +
|
num_indices = num_indices +
|
||||||
(uint16_t)(indices_counts & 0xff);
|
(uint16_t)(indices_counts & 0xff);
|
||||||
indices_counts >>= 8;
|
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 mod_q_mask = q - 1;
|
||||||
uint16_t i, j, k;
|
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 */
|
/* t[(i+k)%N] = sum i=0 through N-1 of a[i], for b[k] = -1 */
|
||||||
|
|
||||||
for (k = 0; k < N; k++)
|
for (k = 0; k < N; k++)
|
||||||
@@ -356,27 +365,19 @@ ntru_ring_mult_product_indices(
|
|||||||
uint16_t mod_q_mask = q - 1;
|
uint16_t mod_q_mask = q - 1;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
assert(a);
|
|
||||||
assert(bi);
|
|
||||||
assert(t);
|
|
||||||
assert(c);
|
|
||||||
|
|
||||||
/* t2 = a * b1 */
|
/* t2 = a * b1 */
|
||||||
|
|
||||||
ntru_ring_mult_indices(a, b1i_len, b1i_len, bi, N, q, t, t2);
|
ntru_ring_mult_indices(a, b1i_len, b1i_len, bi, N, q, t, t2);
|
||||||
|
|
||||||
/* t2 = (a * b1) * b2 */
|
/* t2 = (a * b1) * b2 */
|
||||||
|
|
||||||
ntru_ring_mult_indices(t2, b2i_len, b2i_len, bi + (b1i_len << 1), N, q,
|
ntru_ring_mult_indices(t2, b2i_len, b2i_len, bi + (b1i_len << 1), N, q,
|
||||||
t, t2);
|
t, t2);
|
||||||
|
|
||||||
/* t = a * b3 */
|
/* t = a * b3 */
|
||||||
|
|
||||||
ntru_ring_mult_indices(a, b3i_len, b3i_len,
|
ntru_ring_mult_indices(a, b3i_len, b3i_len,
|
||||||
bi + ((b1i_len + b2i_len) << 1), N, q, t, t);
|
bi + ((b1i_len + b2i_len) << 1), N, q, t, t);
|
||||||
|
|
||||||
/* c = (a * b1 * b2) + (a * b3) */
|
/* c = (a * b1 * b2) + (a * b3) */
|
||||||
|
|
||||||
for (i = 0; i < N; i++)
|
for (i = 0; i < N; i++)
|
||||||
c[i] = (t2[i] + t[i]) & mod_q_mask;
|
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 mod_q_mask = q - 1;
|
||||||
uint16_t i, k;
|
uint16_t i, k;
|
||||||
|
|
||||||
assert(a);
|
|
||||||
assert(b);
|
|
||||||
assert(c);
|
|
||||||
|
|
||||||
/* c[k] = sum(a[i] * b[k-i]) mod q */
|
/* c[k] = sum(a[i] * b[k-i]) mod q */
|
||||||
|
|
||||||
memset(c, 0, N * sizeof(uint16_t));
|
memset(c, 0, N * sizeof(uint16_t));
|
||||||
for (k = 0; k < N; k++) {
|
for (k = 0; k < N; k++) {
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -457,31 +453,22 @@ ntru_ring_inv(
|
|||||||
bool done = FALSE;
|
bool done = FALSE;
|
||||||
uint16_t i, j;
|
uint16_t i, j;
|
||||||
|
|
||||||
assert(a);
|
|
||||||
assert(t);
|
|
||||||
assert(a_inv);
|
|
||||||
|
|
||||||
/* form a^-1 in (Z/2Z)[X]/X^N - 1) */
|
/* 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(X) = 1 */
|
||||||
|
|
||||||
b[0] = 1;
|
b[0] = 1;
|
||||||
deg_b = 0;
|
deg_b = 0;
|
||||||
|
|
||||||
/* c(X) = 0 (cleared above) */
|
/* c(X) = 0 (cleared above) */
|
||||||
|
|
||||||
deg_c = 0;
|
deg_c = 0;
|
||||||
|
|
||||||
/* f(X) = a(X) mod 2 */
|
/* f(X) = a(X) mod 2 */
|
||||||
|
|
||||||
for (i = 0; i < N; i++)
|
for (i = 0; i < N; i++)
|
||||||
f[i] = (uint8_t)(a[i] & 1);
|
f[i] = (uint8_t)(a[i] & 1);
|
||||||
deg_f = N - 1;
|
deg_f = N - 1;
|
||||||
|
|
||||||
/* g(X) = X^N - 1 */
|
/* g(X) = X^N - 1 */
|
||||||
|
|
||||||
g[0] = 1;
|
g[0] = 1;
|
||||||
memset(g + 1, 0, N - 1);
|
memset(g + 1, 0, N - 1);
|
||||||
g[N] = 1;
|
g[N] = 1;
|
||||||
@@ -489,7 +476,8 @@ ntru_ring_inv(
|
|||||||
|
|
||||||
/* until f(X) = 1 */
|
/* until f(X) = 1 */
|
||||||
|
|
||||||
while (!done) {
|
while (!done)
|
||||||
|
{
|
||||||
|
|
||||||
/* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */
|
/* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ extern uint32_t
|
|||||||
ntru_gen_poly(
|
ntru_gen_poly(
|
||||||
hash_algorithm_t hash_algid, /* in - hash algorithm ID for
|
hash_algorithm_t hash_algid, /* in - hash algorithm ID for
|
||||||
IGF-2 */
|
IGF-2 */
|
||||||
uint8_t md_len, /* in - no. of octets in digest */
|
|
||||||
uint8_t min_calls, /* in - minimum no. of hash
|
uint8_t min_calls, /* in - minimum no. of hash
|
||||||
calls */
|
calls */
|
||||||
uint16_t seed_len, /* in - no. of octets in seed */
|
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 <tests/utils/test_rng.h>
|
||||||
#include <plugins/ntru/ntru_drbg.h>
|
#include <plugins/ntru/ntru_drbg.h>
|
||||||
|
#include <plugins/ntru/ntru_mgf1.h>
|
||||||
#include <utils/test.h>
|
#include <utils/test.h>
|
||||||
|
|
||||||
IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create, ntru_drbg_t*,
|
IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create, ntru_drbg_t*,
|
||||||
u_int32_t strength, chunk_t pers_str, rng_t *entropy)
|
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
|
* NTRU parameter sets to test
|
||||||
*/
|
*/
|
||||||
@@ -286,6 +290,169 @@ START_TEST(test_ntru_drbg_reseed)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hash_algorithm_t alg;
|
||||||
|
size_t hash_size;
|
||||||
|
size_t ml1, ml2, ml3;
|
||||||
|
chunk_t seed;
|
||||||
|
chunk_t hashed_seed;
|
||||||
|
chunk_t mask;
|
||||||
|
} mgf1_test_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MGF1 Mask Generation Function Test Vectors
|
||||||
|
*/
|
||||||
|
mgf1_test_t mgf1_tests[] = {
|
||||||
|
{ HASH_SHA1, 20, 60, 20, 15,
|
||||||
|
chunk_from_chars(
|
||||||
|
0xED, 0xA5, 0xC3, 0xBC, 0xAF, 0xB3, 0x20, 0x7D,
|
||||||
|
0x14, 0xA1, 0x54, 0xF7, 0x8B, 0x37, 0xF2, 0x8D,
|
||||||
|
0x8C, 0x9B, 0xD5, 0x63, 0x57, 0x38, 0x11, 0xC2,
|
||||||
|
0xB5, 0xCA, 0xBF, 0x06, 0x43, 0x45, 0x19, 0xD5,
|
||||||
|
0xE7, 0x36, 0xD0, 0x29, 0x21, 0xDA, 0x02, 0x20,
|
||||||
|
0x45, 0xF6, 0x5F, 0x0F, 0x10, 0x04, 0x2A, 0xE3,
|
||||||
|
0x6A, 0x1D, 0xD5, 0x9F, 0x1D, 0x66, 0x44, 0x8F,
|
||||||
|
0xFA, 0xC6, 0xCA, 0xA4, 0x6E, 0x3B, 0x00, 0x66,
|
||||||
|
0xA6, 0xC9, 0x80, 0x5C, 0xF5, 0x2D, 0xD7, 0x72,
|
||||||
|
0xC6, 0xD4, 0x4F, 0x30, 0x72, 0xA2, 0xAD, 0xE0,
|
||||||
|
0x33, 0xE8, 0x55, 0xD5, 0xE6, 0xD6, 0x00, 0x1D,
|
||||||
|
0xA8, 0x68, 0xFF, 0x97, 0x36, 0x8A, 0xF4, 0xD6,
|
||||||
|
0xF1, 0xB6, 0x7E, 0x1F, 0x06, 0xCB, 0x57, 0xCB,
|
||||||
|
0x35, 0x38, 0xF2, 0x2D, 0xF6, 0x20),
|
||||||
|
chunk_from_chars(
|
||||||
|
0xF3, 0x9B, 0x0B, 0xB4, 0x97, 0x50, 0xB5, 0xA7,
|
||||||
|
0xE6, 0xBD, 0xDA, 0xD0, 0x9A, 0x52, 0xBE, 0xA0,
|
||||||
|
0x21, 0xC4, 0x90, 0xB6),
|
||||||
|
chunk_from_chars(
|
||||||
|
0x10, 0x43, 0x76, 0x72, 0x6C, 0xDE, 0xA0, 0x0E,
|
||||||
|
0x77, 0x51, 0xFB, 0x58, 0x39, 0x8A, 0x36, 0xE1,
|
||||||
|
0x63, 0x2B, 0xC9, 0x17, 0x56, 0x0C, 0x4B, 0x46,
|
||||||
|
0xA4, 0x07, 0xA4, 0x3B, 0x8E, 0x33, 0x4D, 0xD1,
|
||||||
|
0x65, 0xF1, 0xAC, 0xC8, 0x59, 0x21, 0x32, 0x16,
|
||||||
|
0x44, 0x2B, 0x7F, 0xB2, 0xA8, 0xA7, 0x26, 0x5D,
|
||||||
|
0xE8, 0x02, 0xBE, 0x8E, 0xDC, 0x34, 0xEB, 0x10,
|
||||||
|
0x76, 0x16, 0x8C, 0xDD, 0x90, 0x92, 0x3D, 0x29,
|
||||||
|
0x90, 0x98, 0x46, 0x11, 0x73, 0x53, 0x47, 0xB1,
|
||||||
|
0x2C, 0xD4, 0x83, 0x78, 0x9B, 0x93, 0x2F, 0x5B,
|
||||||
|
0xFC, 0x26, 0xFF, 0x42, 0x08, 0x1F, 0x70, 0x66,
|
||||||
|
0x40, 0x4B, 0xE7, 0x22, 0x3A, 0x56, 0x10, 0x6D,
|
||||||
|
0x4D, 0x29, 0x0B, 0xCE, 0xA6, 0x21, 0xB5, 0x5C,
|
||||||
|
0x71, 0x66, 0x2F, 0x70, 0x35, 0xD8, 0x8A, 0x92,
|
||||||
|
0x33, 0xF0, 0x16, 0xD4, 0x0E, 0x43, 0x8A, 0x14) },
|
||||||
|
{ HASH_SHA256, 32, 64, 32, 33,
|
||||||
|
chunk_from_chars(
|
||||||
|
0x52, 0xC5, 0xDD, 0x1E, 0xEF, 0x76, 0x1B, 0x53,
|
||||||
|
0x08, 0xE4, 0x86, 0x3F, 0x91, 0x12, 0x98, 0x69,
|
||||||
|
0xC5, 0x9D, 0xDE, 0xF6, 0xFC, 0xFA, 0x93, 0xCE,
|
||||||
|
0x32, 0x52, 0x66, 0xF9, 0xC9, 0x97, 0xF6, 0x42,
|
||||||
|
0x00, 0x2C, 0x64, 0xED, 0x1A, 0x6B, 0x14, 0x0A,
|
||||||
|
0x4B, 0x04, 0xCF, 0x6D, 0x2D, 0x82, 0x0A, 0x07,
|
||||||
|
0xA2, 0x3B, 0xDE, 0xCE, 0x19, 0x8A, 0x39, 0x43,
|
||||||
|
0x16, 0x61, 0x29, 0x98, 0x68, 0xEA, 0xE5, 0xCC,
|
||||||
|
0x0A, 0xF8, 0xE9, 0x71, 0x26, 0xF1, 0x07, 0x36,
|
||||||
|
0x2C, 0x07, 0x1E, 0xEB, 0xE4, 0x28, 0xA2, 0xF4,
|
||||||
|
0xA8, 0x12, 0xC0, 0xC8, 0x20, 0x37, 0xF8, 0xF2,
|
||||||
|
0x6C, 0xAF, 0xDC, 0x6F, 0x2E, 0xD0, 0x62, 0x58,
|
||||||
|
0xD2, 0x37, 0x03, 0x6D, 0xFA, 0x6E, 0x1A, 0xAC,
|
||||||
|
0x9F, 0xCA, 0x56, 0xC6, 0xA4, 0x52, 0x41, 0xE8,
|
||||||
|
0x0F, 0x1B, 0x0C, 0xB9, 0xE6, 0xBA, 0xDE, 0xE1,
|
||||||
|
0x03, 0x5E, 0xC2, 0xE5, 0xF8, 0xF4, 0xF3, 0x46,
|
||||||
|
0x3A, 0x12, 0xC0, 0x1F, 0x3A, 0x00, 0xD0, 0x91,
|
||||||
|
0x18, 0xDD, 0x53, 0xE4, 0x22, 0xF5, 0x26, 0xA4,
|
||||||
|
0x54, 0xEE, 0x20, 0xF0, 0x80),
|
||||||
|
chunk_from_chars(
|
||||||
|
0x76, 0x89, 0x8B, 0x1B, 0x60, 0xEC, 0x10, 0x9D,
|
||||||
|
0x8F, 0x13, 0xF2, 0xFE, 0xD9, 0x85, 0xC1, 0xAB,
|
||||||
|
0x7E, 0xEE, 0xB1, 0x31, 0xDD, 0xF7, 0x7F, 0x0C,
|
||||||
|
0x7D, 0xF9, 0x6B, 0x7B, 0x19, 0x80, 0xBD, 0x28),
|
||||||
|
chunk_from_chars(
|
||||||
|
0xF1, 0x19, 0x02, 0x4F, 0xDA, 0x58, 0x05, 0x9A,
|
||||||
|
0x07, 0xDF, 0x61, 0x81, 0x22, 0x0E, 0x15, 0x46,
|
||||||
|
0xCB, 0x35, 0x3C, 0xDC, 0xAD, 0x20, 0xD9, 0x3F,
|
||||||
|
0x0D, 0xD1, 0xAA, 0x64, 0x66, 0x5C, 0xFA, 0x4A,
|
||||||
|
0xFE, 0xD6, 0x8F, 0x55, 0x57, 0x15, 0xB2, 0xA6,
|
||||||
|
0xA0, 0xE6, 0xA8, 0xC6, 0xBD, 0x28, 0xB4, 0xD5,
|
||||||
|
0x6E, 0x5B, 0x4B, 0xB0, 0x97, 0x09, 0xF5, 0xAC,
|
||||||
|
0x57, 0x65, 0x13, 0x97, 0x71, 0x2C, 0x45, 0x13,
|
||||||
|
0x3D, 0xEE, 0xFB, 0xBF, 0xFE, 0xAF, 0xBB, 0x4B,
|
||||||
|
0x0D, 0x5C, 0x45, 0xD4, 0x2F, 0x17, 0x92, 0x07,
|
||||||
|
0x66, 0x11, 0xF5, 0x46, 0xF8, 0x0C, 0x03, 0x92,
|
||||||
|
0xF5, 0xF5, 0xFF, 0xA4, 0xF3, 0x52, 0xF4, 0x08,
|
||||||
|
0x2C, 0x49, 0x32, 0x1A, 0x93, 0x51, 0x98, 0xB6,
|
||||||
|
0x94, 0x83, 0x39, 0xCF, 0x6B, 0x1F, 0x2F, 0xFC,
|
||||||
|
0x2B, 0xFF, 0x10, 0x71, 0x7D, 0x35, 0x6C, 0xEA,
|
||||||
|
0xC5, 0x66, 0xC7, 0x26, 0x7D, 0x9E, 0xAC, 0xDD,
|
||||||
|
0x35, 0xD7, 0x06, 0x3F, 0x40, 0x82, 0xDA, 0xC3,
|
||||||
|
0x2B, 0x3C, 0x91, 0x3A, 0x32, 0xF8, 0xB2, 0xC6,
|
||||||
|
0x44, 0x4D, 0xCD, 0xB6, 0x54, 0x5F, 0x81, 0x95,
|
||||||
|
0x59, 0xA1, 0xE5, 0x4E, 0xA5, 0x0A, 0x4A, 0x42) }
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_ntru_mgf1)
|
||||||
|
{
|
||||||
|
ntru_mgf1_t *mgf1;
|
||||||
|
chunk_t mask, mask1, mask2, mask3;
|
||||||
|
|
||||||
|
mask1 = mgf1_tests[_i].mask;
|
||||||
|
mask2 = chunk_skip(mask1, mgf1_tests[_i].ml1);
|
||||||
|
mask3 = chunk_skip(mask2, mgf1_tests[_i].ml2);
|
||||||
|
mask1.len = mgf1_tests[_i].ml1;
|
||||||
|
mask2.len = mgf1_tests[_i].ml2;
|
||||||
|
mask3.len = mgf1_tests[_i].ml3;
|
||||||
|
|
||||||
|
mgf1 = ntru_mgf1_create(HASH_UNKNOWN, mgf1_tests[_i].seed, TRUE);
|
||||||
|
ck_assert(mgf1 == NULL);
|
||||||
|
|
||||||
|
mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, chunk_empty, TRUE);
|
||||||
|
ck_assert(mgf1 == NULL);
|
||||||
|
|
||||||
|
/* return mask in allocated chunk */
|
||||||
|
mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE);
|
||||||
|
ck_assert(mgf1);
|
||||||
|
|
||||||
|
/* check hash size */
|
||||||
|
ck_assert(mgf1->get_hash_size(mgf1) == mgf1_tests[_i].hash_size);
|
||||||
|
|
||||||
|
/* get zero number of octets */
|
||||||
|
ck_assert(mgf1->allocate_mask(mgf1, 0, &mask));
|
||||||
|
ck_assert(mask.len == 0 && mask.ptr == NULL);
|
||||||
|
|
||||||
|
/* get non-zero number of octets */
|
||||||
|
ck_assert(mgf1->allocate_mask(mgf1, mgf1_tests[_i].mask.len, &mask));
|
||||||
|
ck_assert(chunk_equals(mask, mgf1_tests[_i].mask));
|
||||||
|
mgf1->destroy(mgf1);
|
||||||
|
|
||||||
|
/* copy mask to pre-allocated buffer */
|
||||||
|
mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE);
|
||||||
|
ck_assert(mgf1);
|
||||||
|
ck_assert(mgf1->get_mask(mgf1, mgf1_tests[_i].mask.len, mask.ptr));
|
||||||
|
ck_assert(chunk_equals(mask, mgf1_tests[_i].mask));
|
||||||
|
mgf1->destroy(mgf1);
|
||||||
|
|
||||||
|
/* get mask in batches without hashing the seed */
|
||||||
|
mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].hashed_seed, FALSE);
|
||||||
|
ck_assert(mgf1);
|
||||||
|
|
||||||
|
/* first batch */
|
||||||
|
ck_assert(mgf1->get_mask(mgf1, mask1.len, mask.ptr));
|
||||||
|
mask.len = mask1.len;
|
||||||
|
ck_assert(chunk_equals(mask, mask1));
|
||||||
|
|
||||||
|
/* second batch */
|
||||||
|
ck_assert(mgf1->get_mask(mgf1, mask2.len, mask.ptr));
|
||||||
|
mask.len = mask2.len;
|
||||||
|
ck_assert(chunk_equals(mask, mask2));
|
||||||
|
|
||||||
|
/* third batch */
|
||||||
|
ck_assert(mgf1->get_mask(mgf1, mask3.len, mask.ptr));
|
||||||
|
mask.len = mask3.len;
|
||||||
|
ck_assert(chunk_equals(mask, mask3));
|
||||||
|
|
||||||
|
mgf1->destroy(mgf1);
|
||||||
|
chunk_free(&mask);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_ntru_ke)
|
START_TEST(test_ntru_ke)
|
||||||
{
|
{
|
||||||
chunk_t pub_key, cipher_text, i_shared_secret, r_shared_secret;
|
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);
|
tcase_add_test(tc, test_ntru_drbg_reseed);
|
||||||
suite_add_tcase(s, tc);
|
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");
|
tc = tcase_create("ke");
|
||||||
tcase_add_loop_test(tc, test_ntru_ke, 0, countof(params));
|
tcase_add_loop_test(tc, test_ntru_ke, 0, countof(params));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|||||||
Reference in New Issue
Block a user