mirror of
https://github.com/strongswan/strongswan.git
synced 2025-12-05 00:01:49 -05:00
Completed integration of ntru_crypto library into ntru plugin
This commit is contained in:
parent
b517912848
commit
22e1aa51f9
@ -12,6 +12,7 @@ endif
|
||||
|
||||
libstrongswan_ntru_la_SOURCES = \
|
||||
ntru_plugin.h ntru_plugin.c \
|
||||
ntru_convert.h ntru_convert.c \
|
||||
ntru_drbg.h ntru_drbg.c \
|
||||
ntru_ke.h ntru_ke.c \
|
||||
ntru_mgf1.h ntru_mgf1.c \
|
||||
@ -19,15 +20,7 @@ libstrongswan_ntru_la_SOURCES = \
|
||||
ntru_poly.h ntru_poly.c \
|
||||
ntru_public_key.h ntru_public_key.c \
|
||||
ntru_private_key.h ntru_private_key.c \
|
||||
ntru_trits.h ntru_trits.c \
|
||||
ntru_crypto/ntru_crypto.h \
|
||||
ntru_crypto/ntru_crypto_ntru_convert.h \
|
||||
ntru_crypto/ntru_crypto_ntru_convert.c \
|
||||
ntru_crypto/ntru_crypto_ntru_encrypt.c \
|
||||
ntru_crypto/ntru_crypto_ntru_encrypt_key.h \
|
||||
ntru_crypto/ntru_crypto_ntru_encrypt_key.c \
|
||||
ntru_crypto/ntru_crypto_ntru_poly.h \
|
||||
ntru_crypto/ntru_crypto_ntru_poly.c
|
||||
ntru_trits.h ntru_trits.c
|
||||
|
||||
libstrongswan_ntru_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
|
||||
452
src/libstrongswan/plugins/ntru/ntru_convert.c
Normal file
452
src/libstrongswan/plugins/ntru/ntru_convert.c
Normal file
@ -0,0 +1,452 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ntru_convert.h"
|
||||
|
||||
/**
|
||||
* 3-bit to 2-trit conversion tables: 2 represents -1
|
||||
*/
|
||||
static uint8_t const bits_2_trit1[] = {0, 0, 0, 1, 1, 1, 2, 2};
|
||||
static uint8_t const bits_2_trit2[] = {0, 1, 2, 0, 1, 2, 0, 1};
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_bits_2_trits(uint8_t const *octets, uint16_t num_trits, uint8_t *trits)
|
||||
{
|
||||
uint32_t bits24, bits3, shift;
|
||||
|
||||
while (num_trits >= 16)
|
||||
{
|
||||
/* get next three octets */
|
||||
bits24 = ((uint32_t)(*octets++)) << 16;
|
||||
bits24 |= ((uint32_t)(*octets++)) << 8;
|
||||
bits24 |= (uint32_t)(*octets++);
|
||||
|
||||
/* for each 3 bits in the three octets, output 2 trits */
|
||||
bits3 = (bits24 >> 21) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 18) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 15) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 12) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 9) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 6) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 3) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = bits24 & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
num_trits -= 16;
|
||||
}
|
||||
if (num_trits == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* get three octets */
|
||||
bits24 = ((uint32_t)(*octets++)) << 16;
|
||||
bits24 |= ((uint32_t)(*octets++)) << 8;
|
||||
bits24 |= (uint32_t)(*octets++);
|
||||
|
||||
shift = 21;
|
||||
while (num_trits)
|
||||
{
|
||||
/**
|
||||
* for each 3 bits in the three octets, output up to 2 trits
|
||||
* until all trits needed are produced
|
||||
*/
|
||||
bits3 = (bits24 >> shift) & 0x7;
|
||||
shift -= 3;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
if (--num_trits)
|
||||
{
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
--num_trits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
bool ntru_trits_2_bits(uint8_t const *trits, uint32_t num_trits, uint8_t *octets)
|
||||
{
|
||||
bool all_trits_valid = TRUE;
|
||||
uint32_t bits24, bits3, shift;
|
||||
|
||||
while (num_trits >= 16)
|
||||
{
|
||||
/* convert each 2 trits to 3 bits and pack */
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 = (bits3 << 21);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 18);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 15);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 12);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 9);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 6);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 3);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= bits3;
|
||||
|
||||
num_trits -= 16;
|
||||
|
||||
/* output three octets */
|
||||
*octets++ = (uint8_t)((bits24 >> 16) & 0xff);
|
||||
*octets++ = (uint8_t)((bits24 >> 8) & 0xff);
|
||||
*octets++ = (uint8_t)(bits24 & 0xff);
|
||||
}
|
||||
|
||||
bits24 = 0;
|
||||
shift = 21;
|
||||
while (num_trits)
|
||||
{
|
||||
/* convert each 2 trits to 3 bits and pack */
|
||||
bits3 = *trits++ * 3;
|
||||
if (--num_trits)
|
||||
{
|
||||
bits3 += *trits++;
|
||||
--num_trits;
|
||||
}
|
||||
if (bits3 > 7)
|
||||
{
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << shift);
|
||||
shift -= 3;
|
||||
}
|
||||
|
||||
/* output three octets */
|
||||
*octets++ = (uint8_t)((bits24 >> 16) & 0xff);
|
||||
*octets++ = (uint8_t)((bits24 >> 8) & 0xff);
|
||||
*octets++ = (uint8_t)(bits24 & 0xff);
|
||||
|
||||
return all_trits_valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
void ntru_coeffs_mod4_2_octets(uint16_t num_coeffs, uint16_t const *coeffs, uint8_t *octets)
|
||||
{
|
||||
uint8_t bits2;
|
||||
int shift, i;
|
||||
|
||||
*octets = 0;
|
||||
shift = 6;
|
||||
for (i = 0; i < num_coeffs; i++)
|
||||
{
|
||||
bits2 = (uint8_t)(coeffs[i] & 0x3);
|
||||
*octets |= bits2 << shift;
|
||||
shift -= 2;
|
||||
if (shift < 0)
|
||||
{
|
||||
++octets;
|
||||
*octets = 0;
|
||||
shift = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_trits_2_octet(uint8_t const *trits, uint8_t *octet)
|
||||
{
|
||||
int i;
|
||||
|
||||
*octet = 0;
|
||||
for (i = 4; i >= 0; i--)
|
||||
{
|
||||
*octet = (*octet * 3) + trits[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_octet_2_trits(uint8_t octet, uint8_t *trits)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
trits[i] = octet % 3;
|
||||
octet = (octet - trits[i]) / 3;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_indices_2_trits(uint16_t in_len, uint16_t const *in, bool plus1,
|
||||
uint8_t *out)
|
||||
{
|
||||
uint8_t trit = plus1 ? 1 : 2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < in_len; i++)
|
||||
{
|
||||
out[in[i]] = trit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_packed_trits_2_indices(uint8_t const *in, uint16_t num_trits,
|
||||
uint16_t *indices_plus1,
|
||||
uint16_t *indices_minus1)
|
||||
{
|
||||
uint8_t trits[5];
|
||||
uint16_t i = 0;
|
||||
int j;
|
||||
|
||||
while (num_trits >= 5)
|
||||
{
|
||||
ntru_octet_2_trits(*in++, trits);
|
||||
num_trits -= 5;
|
||||
for (j = 0; j < 5; j++, i++)
|
||||
{
|
||||
if (trits[j] == 1)
|
||||
{
|
||||
*indices_plus1 = i;
|
||||
++indices_plus1;
|
||||
}
|
||||
else if (trits[j] == 2)
|
||||
{
|
||||
*indices_minus1 = i;
|
||||
++indices_minus1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_trits)
|
||||
{
|
||||
ntru_octet_2_trits(*in, trits);
|
||||
for (j = 0; num_trits && (j < 5); j++, i++)
|
||||
{
|
||||
if (trits[j] == 1)
|
||||
{
|
||||
*indices_plus1 = i;
|
||||
++indices_plus1;
|
||||
}
|
||||
else if (trits[j] == 2)
|
||||
{
|
||||
*indices_minus1 = i;
|
||||
++indices_minus1;
|
||||
}
|
||||
--num_trits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_indices_2_packed_trits(uint16_t const *indices, uint16_t num_plus1,
|
||||
uint16_t num_minus1, uint16_t num_trits,
|
||||
uint8_t *buf, uint8_t *out)
|
||||
{
|
||||
/* convert indices to an array of trits */
|
||||
memset(buf, 0, num_trits);
|
||||
ntru_indices_2_trits(num_plus1, indices, TRUE, buf);
|
||||
ntru_indices_2_trits(num_minus1, indices + num_plus1, FALSE, buf);
|
||||
|
||||
/* pack the array of trits */
|
||||
while (num_trits >= 5)
|
||||
{
|
||||
ntru_trits_2_octet(buf, out);
|
||||
num_trits -= 5;
|
||||
buf += 5;
|
||||
++out;
|
||||
}
|
||||
if (num_trits)
|
||||
{
|
||||
uint8_t trits[5];
|
||||
|
||||
memcpy(trits, buf, num_trits);
|
||||
memset(trits + num_trits, 0, sizeof(trits) - num_trits);
|
||||
ntru_trits_2_octet(trits, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
void ntru_elements_2_octets(uint16_t in_len, uint16_t const *in, uint8_t n_bits,
|
||||
uint8_t *out)
|
||||
{
|
||||
uint16_t temp;
|
||||
int shift, i;
|
||||
|
||||
/* pack */
|
||||
temp = 0;
|
||||
shift = n_bits - 8;
|
||||
i = 0;
|
||||
while (i < in_len)
|
||||
{
|
||||
/* add bits to temp to fill an octet and output the octet */
|
||||
temp |= in[i] >> shift;
|
||||
*out++ = (uint8_t)(temp & 0xff);
|
||||
shift = 8 - shift;
|
||||
if (shift < 1)
|
||||
{
|
||||
/* next full octet is in current input word */
|
||||
shift += n_bits;
|
||||
temp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* put remaining bits of input word in temp as partial octet,
|
||||
* and increment index to next input word
|
||||
*/
|
||||
temp = in[i] << (uint16_t)shift;
|
||||
++i;
|
||||
}
|
||||
shift = n_bits - shift;
|
||||
}
|
||||
|
||||
/* output any bits remaining in last input word */
|
||||
if (shift != n_bits - 8)
|
||||
{
|
||||
*out++ = (uint8_t)(temp & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
void ntru_octets_2_elements(uint16_t in_len, uint8_t const *in, uint8_t n_bits,
|
||||
uint16_t *out)
|
||||
{
|
||||
uint16_t temp;
|
||||
uint16_t mask = (1 << n_bits) - 1;
|
||||
int shift, i;
|
||||
|
||||
/* unpack */
|
||||
temp = 0;
|
||||
shift = n_bits;
|
||||
i = 0;
|
||||
while (i < in_len)
|
||||
{
|
||||
shift = 8 - shift;
|
||||
if (shift < 0)
|
||||
{
|
||||
/* the current octet will not fill the current element */
|
||||
shift += n_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add bits from the current octet to fill the current element and
|
||||
* output the element
|
||||
*/
|
||||
temp |= ((uint16_t)in[i]) >> shift;
|
||||
*out++ = temp & mask;
|
||||
temp = 0;
|
||||
}
|
||||
|
||||
/* add the remaining bits of the current octet to start an element */
|
||||
shift = n_bits - shift;
|
||||
temp |= ((uint16_t)in[i]) << shift;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
147
src/libstrongswan/plugins/ntru/ntru_convert.h
Normal file
147
src/libstrongswan/plugins/ntru/ntru_convert.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. 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_convert ntru_convert
|
||||
* @{ @ingroup ntru_p
|
||||
*/
|
||||
|
||||
#ifndef NTRU_CONVERT_H_
|
||||
#define NTRU_CONVERT_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* Each 3 bits in an array of octets is converted to 2 trits in an array
|
||||
* of trits.
|
||||
*
|
||||
* @param octets pointer to array of octets
|
||||
* @param num_trits number of trits to produce
|
||||
* @param trits address for array of trits
|
||||
*/
|
||||
void ntru_bits_2_trits(uint8_t const *octets, uint16_t num_trits,
|
||||
uint8_t *trits);
|
||||
|
||||
/**
|
||||
* Each 2 trits in an array of trits is converted to 3 bits, and the bits
|
||||
* are packed in an array of octets. A multiple of 3 octets is output.
|
||||
* Any bits in the final octets not derived from trits are zero.
|
||||
*
|
||||
* @param trits pointer to array of trits
|
||||
* @param num_trits number of trits to convert
|
||||
* @param octets address for array of octets
|
||||
* @return TRUE if all trits were valid
|
||||
* FALSE if invalid trits were found
|
||||
*/
|
||||
bool ntru_trits_2_bits(uint8_t const *trits, uint32_t num_trits,
|
||||
uint8_t *octets);
|
||||
|
||||
/**
|
||||
* Takes an array of coefficients mod 4 and packs the results into an
|
||||
* octet string.
|
||||
*
|
||||
* @param num_coeffs number of coefficients
|
||||
* @param coeffs pointer to coefficients
|
||||
* @param octets address for octets
|
||||
*/
|
||||
void ntru_coeffs_mod4_2_octets(uint16_t num_coeffs, uint16_t const *coeffs,
|
||||
uint8_t *octets);
|
||||
|
||||
/**
|
||||
* Packs 5 trits in an octet, where a trit is 0, 1, or 2 (-1).
|
||||
*
|
||||
* @param trits pointer to trits
|
||||
* @param octet address for octet
|
||||
*/
|
||||
void ntru_trits_2_octet(uint8_t const *trits, uint8_t *octet);
|
||||
|
||||
/**
|
||||
* Unpacks an octet to 5 trits, where a trit is 0, 1, or 2 (-1).
|
||||
*
|
||||
* @param octet octet to be unpacked
|
||||
* @param trits address for trits
|
||||
*/
|
||||
void ntru_octet_2_trits(uint8_t octet, uint8_t *trits);
|
||||
|
||||
/**
|
||||
*
|
||||
* Converts a list of the nonzero indices of a polynomial into an array of
|
||||
* trits.
|
||||
*
|
||||
* @param in_len no. of indices
|
||||
* @param in pointer to list of indices
|
||||
* @param plus1 if list is +1 coefficients
|
||||
* @param out address of output polynomial
|
||||
*/
|
||||
void ntru_indices_2_trits(uint16_t in_len, uint16_t const *in, bool plus1,
|
||||
uint8_t *out);
|
||||
|
||||
/**
|
||||
* Unpacks an array of N trits and creates a list of array indices
|
||||
* corresponding to trits = +1, and list of array indices corresponding to
|
||||
* trits = -1.
|
||||
*
|
||||
* @param in pointer to packed-trit octets
|
||||
* @param num_trits no. of packed trits
|
||||
* @param indices_plus1 address for indices of +1 trits
|
||||
* @param indices_minus1 address for indices of -1 trits
|
||||
*/
|
||||
void ntru_packed_trits_2_indices(uint8_t const *in, uint16_t num_trits,
|
||||
uint16_t *indices_plus1,
|
||||
uint16_t *indices_minus1);
|
||||
|
||||
/**
|
||||
* Takes a list of array indices corresponding to elements whose values
|
||||
* are +1 or -1, and packs the N-element array of trits described by these
|
||||
* lists into octets, 5 trits per octet.
|
||||
*
|
||||
* @param indices pointer to indices
|
||||
* @param num_plus1 no. of indices for +1 trits
|
||||
* @param num_minus1 no. of indices for -1 trits
|
||||
* @param num_trits N, no. of trits in array
|
||||
* @param buf temp buf, N octets
|
||||
* @param out address for packed octet
|
||||
*/
|
||||
void ntru_indices_2_packed_trits(uint16_t const *indices, uint16_t num_plus1,
|
||||
uint16_t num_minus1, uint16_t num_trits,
|
||||
uint8_t *buf, uint8_t *out);
|
||||
|
||||
/**
|
||||
* Packs an array of n-bit elements into an array of
|
||||
* ((in_len * n_bits) + 7) / 8 octets, 8 < n_bits < 16.
|
||||
*
|
||||
* @param in_len no. of elements to be packed
|
||||
* @param in ptr to elements to be packed
|
||||
* @param n_bits no. of bits in input element
|
||||
* @param out addr for output octets
|
||||
*/
|
||||
void ntru_elements_2_octets(uint16_t in_len, uint16_t const *in, uint8_t n_bits,
|
||||
uint8_t *out);
|
||||
|
||||
/**
|
||||
* Unpacks an octet string into an array of ((in_len * 8) / n_bits)
|
||||
* n-bit elements, 8 < n < 16. Any extra bits are discarded.
|
||||
*
|
||||
* @param in_len no. of octets to be unpacked
|
||||
* @param in ptr to octets to be unpacked
|
||||
* @param n_bits no. of bits in output element
|
||||
* @param out addr for output elements
|
||||
*/
|
||||
void ntru_octets_2_elements(uint16_t in_len, uint8_t const *in, uint8_t n_bits,
|
||||
uint16_t *out);
|
||||
|
||||
#endif /** NTRU_CONVERT_H_ @}*/
|
||||
@ -1,116 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto.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.h
|
||||
*
|
||||
* Contents: Public header file for NTRUEncrypt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NTRU_CRYPTO_H
|
||||
#define NTRU_CRYPTO_H
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#include "ntru_param_set.h"
|
||||
#include "ntru_drbg.h"
|
||||
|
||||
#if !defined( NTRUCALL )
|
||||
#if !defined(WIN32) || defined (NTRUCRYPTO_STATIC)
|
||||
// Linux, or a Win32 static library
|
||||
#define NTRUCALL extern uint32_t
|
||||
#elif defined (NTRUCRYPTO_EXPORTS)
|
||||
// Win32 DLL build
|
||||
#define NTRUCALL extern __declspec(dllexport) uint32_t
|
||||
#else
|
||||
// Win32 DLL import
|
||||
#define NTRUCALL extern __declspec(dllimport) uint32_t
|
||||
#endif
|
||||
#endif /* NTRUCALL */
|
||||
|
||||
/* error codes */
|
||||
|
||||
#define NTRU_OK 0
|
||||
#define NTRU_FAIL 1
|
||||
#define NTRU_BAD_PARAMETER 2
|
||||
#define NTRU_BAD_LENGTH 3
|
||||
#define NTRU_BUFFER_TOO_SMALL 4
|
||||
#define NTRU_INVALID_PARAMETER_SET 5
|
||||
#define NTRU_BAD_PUBLIC_KEY 6
|
||||
#define NTRU_BAD_PRIVATE_KEY 7
|
||||
#define NTRU_OUT_OF_MEMORY 8
|
||||
#define NTRU_BAD_ENCODING 9
|
||||
#define NTRU_OID_NOT_RECOGNIZED 10
|
||||
#define NTRU_DRBG_FAIL 11
|
||||
#define NTRU_MGF1_FAIL 12
|
||||
|
||||
/* function declarations */
|
||||
|
||||
/* ntru_crypto_ntru_encrypt
|
||||
*
|
||||
* Implements NTRU encryption (SVES) for the parameter set specified in
|
||||
* the public key blob.
|
||||
*
|
||||
* 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 ciphertext buffer (ct) may be
|
||||
* queried by invoking this function with ct = NULL. In this case, no
|
||||
* encryption is performed, NTRU_OK is returned, and the required minimum
|
||||
* size for ct is returned in ct_len.
|
||||
*
|
||||
* When ct != NULL, at invocation *ct_len must be the size of the ct buffer.
|
||||
* Upon return it is the actual size of the ciphertext.
|
||||
*
|
||||
* Returns NTRU_OK if successful.
|
||||
* 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
|
||||
ntru_crypto_ntru_encrypt(
|
||||
ntru_drbg_t *drbg , /* in - handle for DRBG */
|
||||
uint16_t pubkey_blob_len, /* in - no. of octets in public key
|
||||
blob */
|
||||
uint8_t const *pubkey_blob, /* in - pointer to public key */
|
||||
uint16_t pt_len, /* in - no. of octets in plaintext */
|
||||
uint8_t const *pt, /* in - pointer to plaintext */
|
||||
uint16_t *ct_len, /* in/out - no. of octets in ct, addr for
|
||||
no. of octets in ciphertext */
|
||||
uint8_t *ct); /* out - address for ciphertext */
|
||||
|
||||
#endif /* NTRU_CRYPTO_H */
|
||||
@ -1,581 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_convert.c 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_ntru_convert.c
|
||||
*
|
||||
* Contents: Conversion routines for NTRUEncrypt, including packing, unpacking,
|
||||
* and others.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "ntru_crypto_ntru_convert.h"
|
||||
|
||||
|
||||
/* 3-bit to 2-trit conversion tables: 2 represents -1 */
|
||||
|
||||
static uint8_t const bits_2_trit1[] = {0, 0, 0, 1, 1, 1, 2, 2};
|
||||
static uint8_t const bits_2_trit2[] = {0, 1, 2, 0, 1, 2, 0, 1};
|
||||
|
||||
|
||||
/* ntru_bits_2_trits
|
||||
*
|
||||
* Each 3 bits in an array of octets is converted to 2 trits in an array
|
||||
* of trits.
|
||||
*
|
||||
* The octet array may overlap the end of the trit array.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_bits_2_trits(
|
||||
uint8_t const *octets, /* in - pointer to array of octets */
|
||||
uint16_t num_trits, /* in - number of trits to produce */
|
||||
uint8_t *trits) /* out - address for array of trits */
|
||||
{
|
||||
uint32_t bits24;
|
||||
uint32_t bits3;
|
||||
uint32_t shift;
|
||||
|
||||
assert(octets);
|
||||
assert(trits);
|
||||
|
||||
while (num_trits >= 16) {
|
||||
|
||||
/* get next three octets */
|
||||
|
||||
bits24 = ((uint32_t)(*octets++)) << 16;
|
||||
bits24 |= ((uint32_t)(*octets++)) << 8;
|
||||
bits24 |= (uint32_t)(*octets++);
|
||||
|
||||
/* for each 3 bits in the three octets, output 2 trits */
|
||||
|
||||
bits3 = (bits24 >> 21) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 18) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 15) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 12) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 9) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 6) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = (bits24 >> 3) & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
bits3 = bits24 & 0x7;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
|
||||
num_trits -= 16;
|
||||
}
|
||||
if (num_trits == 0)
|
||||
return;
|
||||
|
||||
/* get three octets */
|
||||
|
||||
bits24 = ((uint32_t)(*octets++)) << 16;
|
||||
bits24 |= ((uint32_t)(*octets++)) << 8;
|
||||
bits24 |= (uint32_t)(*octets++);
|
||||
|
||||
shift = 21;
|
||||
while (num_trits) {
|
||||
|
||||
/* for each 3 bits in the three octets, output up to 2 trits
|
||||
* until all trits needed are produced
|
||||
*/
|
||||
|
||||
bits3 = (bits24 >> shift) & 0x7;
|
||||
shift -= 3;
|
||||
*trits++ = bits_2_trit1[bits3];
|
||||
if (--num_trits) {
|
||||
*trits++ = bits_2_trit2[bits3];
|
||||
--num_trits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_trits_2_bits
|
||||
*
|
||||
* Each 2 trits in an array of trits is converted to 3 bits, and the bits
|
||||
* are packed in an array of octets. A multiple of 3 octets is output.
|
||||
* Any bits in the final octets not derived from trits are zero.
|
||||
*
|
||||
* Returns TRUE if all trits were valid.
|
||||
* Returns FALSE if invalid trits were found.
|
||||
*/
|
||||
|
||||
bool
|
||||
ntru_trits_2_bits(
|
||||
uint8_t const *trits, /* in - pointer to array of trits */
|
||||
uint32_t num_trits, /* in - number of trits to convert */
|
||||
uint8_t *octets) /* out - address for array of octets */
|
||||
{
|
||||
bool all_trits_valid = TRUE;
|
||||
uint32_t bits24;
|
||||
uint32_t bits3;
|
||||
uint32_t shift;
|
||||
|
||||
assert(octets);
|
||||
assert(trits);
|
||||
|
||||
while (num_trits >= 16) {
|
||||
|
||||
/* convert each 2 trits to 3 bits and pack */
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 = (bits3 << 21);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 18);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 15);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 12);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 9);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 6);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << 3);
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
bits3 += *trits++;
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= bits3;
|
||||
|
||||
num_trits -= 16;
|
||||
|
||||
/* output three octets */
|
||||
|
||||
*octets++ = (uint8_t)((bits24 >> 16) & 0xff);
|
||||
*octets++ = (uint8_t)((bits24 >> 8) & 0xff);
|
||||
*octets++ = (uint8_t)(bits24 & 0xff);
|
||||
}
|
||||
|
||||
bits24 = 0;
|
||||
shift = 21;
|
||||
while (num_trits) {
|
||||
|
||||
/* convert each 2 trits to 3 bits and pack */
|
||||
|
||||
bits3 = *trits++ * 3;
|
||||
if (--num_trits) {
|
||||
bits3 += *trits++;
|
||||
--num_trits;
|
||||
}
|
||||
if (bits3 > 7) {
|
||||
bits3 = 7;
|
||||
all_trits_valid = FALSE;
|
||||
}
|
||||
bits24 |= (bits3 << shift);
|
||||
shift -= 3;
|
||||
}
|
||||
|
||||
/* output three octets */
|
||||
|
||||
*octets++ = (uint8_t)((bits24 >> 16) & 0xff);
|
||||
*octets++ = (uint8_t)((bits24 >> 8) & 0xff);
|
||||
*octets++ = (uint8_t)(bits24 & 0xff);
|
||||
|
||||
return all_trits_valid;
|
||||
}
|
||||
|
||||
|
||||
/* ntru_coeffs_mod4_2_octets
|
||||
*
|
||||
* Takes an array of ring element coefficients mod 4 and packs the
|
||||
* results into an octet string.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_coeffs_mod4_2_octets(
|
||||
uint16_t num_coeffs, /* in - number of coefficients */
|
||||
uint16_t const *coeffs, /* in - pointer to coefficients */
|
||||
uint8_t *octets) /* out - address for octets */
|
||||
{
|
||||
uint8_t bits2;
|
||||
int shift;
|
||||
uint16_t i;
|
||||
|
||||
assert(coeffs);
|
||||
assert(octets);
|
||||
|
||||
*octets = 0;
|
||||
shift = 6;
|
||||
for (i = 0; i < num_coeffs; i++) {
|
||||
bits2 = (uint8_t)(coeffs[i] & 0x3);
|
||||
*octets |= bits2 << shift;
|
||||
shift -= 2;
|
||||
if (shift < 0) {
|
||||
++octets;
|
||||
*octets = 0;
|
||||
shift = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_trits_2_octet
|
||||
*
|
||||
* Packs 5 trits in an octet, where a trit is 0, 1, or 2 (-1).
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_trits_2_octet(
|
||||
uint8_t const *trits, /* in - pointer to trits */
|
||||
uint8_t *octet) /* out - address for octet */
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(trits);
|
||||
assert(octet);
|
||||
|
||||
*octet = 0;
|
||||
for (i = 4; i >= 0; i--) {
|
||||
*octet = (*octet * 3) + trits[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_octet_2_trits
|
||||
*
|
||||
* Unpacks an octet to 5 trits, where a trit is 0, 1, or 2 (-1).
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_octet_2_trits(
|
||||
uint8_t octet, /* in - octet to be unpacked */
|
||||
uint8_t *trits) /* out - address for trits */
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(trits);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
trits[i] = octet % 3;
|
||||
octet = (octet - trits[i]) / 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_indices_2_trits
|
||||
*
|
||||
* Converts a list of the nonzero indices of a polynomial into an array of
|
||||
* trits.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_indices_2_trits(
|
||||
uint16_t in_len, /* in - no. of indices */
|
||||
uint16_t const *in, /* in - pointer to list of indices */
|
||||
bool plus1, /* in - if list is +1 cofficients */
|
||||
uint8_t *out) /* out - address of output polynomial */
|
||||
{
|
||||
uint8_t trit = plus1 ? 1 : 2;
|
||||
uint16_t i;
|
||||
|
||||
assert(in);
|
||||
assert(out);
|
||||
|
||||
for (i = 0; i < in_len; i++) {
|
||||
out[in[i]] = trit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_packed_trits_2_indices
|
||||
*
|
||||
* Unpacks an array of N trits and creates a list of array indices
|
||||
* corresponding to trits = +1, and list of array indices corresponding to
|
||||
* trits = -1.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_packed_trits_2_indices(
|
||||
uint8_t const *in, /* in - pointer to packed-trit octets */
|
||||
uint16_t num_trits, /* in - no. of packed trits */
|
||||
uint16_t *indices_plus1, /* out - address for indices of +1 trits */
|
||||
uint16_t *indices_minus1) /* out - address for indices of -1 trits */
|
||||
{
|
||||
uint8_t trits[5];
|
||||
uint16_t i = 0;
|
||||
int j;
|
||||
|
||||
assert(in);
|
||||
assert(indices_plus1);
|
||||
assert(indices_minus1);
|
||||
|
||||
while (num_trits >= 5) {
|
||||
ntru_octet_2_trits(*in++, trits);
|
||||
num_trits -= 5;
|
||||
for (j = 0; j < 5; j++, i++) {
|
||||
if (trits[j] == 1) {
|
||||
*indices_plus1 = i;
|
||||
++indices_plus1;
|
||||
} else if (trits[j] == 2) {
|
||||
*indices_minus1 = i;
|
||||
++indices_minus1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_trits) {
|
||||
ntru_octet_2_trits(*in, trits);
|
||||
for (j = 0; num_trits && (j < 5); j++, i++) {
|
||||
if (trits[j] == 1) {
|
||||
*indices_plus1 = i;
|
||||
++indices_plus1;
|
||||
} else if (trits[j] == 2) {
|
||||
*indices_minus1 = i;
|
||||
++indices_minus1;
|
||||
}
|
||||
--num_trits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_indices_2_packed_trits
|
||||
*
|
||||
* Takes a list of array indices corresponding to elements whose values
|
||||
* are +1 or -1, and packs the N-element array of trits described by these
|
||||
* lists into octets, 5 trits per octet.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_indices_2_packed_trits(
|
||||
uint16_t const *indices, /* in - pointer to indices */
|
||||
uint16_t num_plus1, /* in - no. of indices for +1 trits */
|
||||
uint16_t num_minus1, /* in - no. of indices for -1 trits */
|
||||
uint16_t num_trits, /* in - N, no. of trits in array */
|
||||
uint8_t *buf, /* in - temp buf, N octets */
|
||||
uint8_t *out) /* out - address for packed octets */
|
||||
{
|
||||
assert(indices);
|
||||
assert(buf);
|
||||
assert(out);
|
||||
|
||||
/* convert indices to an array of trits */
|
||||
|
||||
memset(buf, 0, num_trits);
|
||||
ntru_indices_2_trits(num_plus1, indices, TRUE, buf);
|
||||
ntru_indices_2_trits(num_minus1, indices + num_plus1, FALSE, buf);
|
||||
|
||||
/* pack the array of trits */
|
||||
|
||||
while (num_trits >= 5) {
|
||||
ntru_trits_2_octet(buf, out);
|
||||
num_trits -= 5;
|
||||
buf += 5;
|
||||
++out;
|
||||
}
|
||||
if (num_trits) {
|
||||
uint8_t trits[5];
|
||||
|
||||
memcpy(trits, buf, num_trits);
|
||||
memset(trits + num_trits, 0, sizeof(trits) - num_trits);
|
||||
ntru_trits_2_octet(trits, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_elements_2_octets
|
||||
*
|
||||
* Packs an array of n-bit elements into an array of
|
||||
* ((in_len * n_bits) + 7) / 8 octets, 8 < n_bits < 16.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_elements_2_octets(
|
||||
uint16_t in_len, /* in - no. of elements to be packed */
|
||||
uint16_t const *in, /* in - ptr to elements to be packed */
|
||||
uint8_t n_bits, /* in - no. of bits in input element */
|
||||
uint8_t *out) /* out - addr for output octets */
|
||||
{
|
||||
uint16_t temp;
|
||||
int shift;
|
||||
uint16_t i;
|
||||
|
||||
assert(in_len);
|
||||
assert(in);
|
||||
assert((n_bits > 8) && (n_bits < 16));
|
||||
assert(out);
|
||||
|
||||
/* pack */
|
||||
|
||||
temp = 0;
|
||||
shift = n_bits - 8;
|
||||
i = 0;
|
||||
while (i < in_len) {
|
||||
|
||||
/* add bits to temp to fill an octet and output the octet */
|
||||
|
||||
temp |= in[i] >> shift;
|
||||
*out++ = (uint8_t)(temp & 0xff);
|
||||
shift = 8 - shift;
|
||||
if (shift < 1) {
|
||||
|
||||
/* next full octet is in current input word */
|
||||
|
||||
shift += n_bits;
|
||||
temp = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* put remaining bits of input word in temp as partial octet,
|
||||
* and increment index to next input word
|
||||
*/
|
||||
temp = in[i] << (uint16_t)shift;
|
||||
|
||||
++i;
|
||||
}
|
||||
shift = n_bits - shift;
|
||||
}
|
||||
|
||||
/* output any bits remaining in last input word */
|
||||
|
||||
if (shift != n_bits - 8) {
|
||||
*out++ = (uint8_t)(temp & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ntru_octets_2_elements
|
||||
*
|
||||
* Unpacks an octet string into an array of ((in_len * 8) / n_bits)
|
||||
* n-bit elements, 8 < n_bits < 16. Any extra bits are discarded.
|
||||
*/
|
||||
|
||||
void
|
||||
ntru_octets_2_elements(
|
||||
uint16_t in_len, /* in - no. of octets to be unpacked */
|
||||
uint8_t const *in, /* in - ptr to octets to be unpacked */
|
||||
uint8_t n_bits, /* in - no. of bits in output element */
|
||||
uint16_t *out) /* out - addr for output elements */
|
||||
{
|
||||
uint16_t temp;
|
||||
uint16_t mask = (1 << n_bits) - 1;
|
||||
int shift;
|
||||
uint16_t i;
|
||||
|
||||
assert(in_len > 1);
|
||||
assert(in);
|
||||
assert((n_bits > 8) && (n_bits < 16));
|
||||
assert(out);
|
||||
|
||||
/* unpack */
|
||||
|
||||
temp = 0;
|
||||
shift = n_bits;
|
||||
i = 0;
|
||||
while (i < in_len) {
|
||||
shift = 8 - shift;
|
||||
if (shift < 0) {
|
||||
|
||||
/* the current octet will not fill the current element */
|
||||
|
||||
shift += n_bits;
|
||||
|
||||
} else {
|
||||
|
||||
/* add bits from the current octet to fill the current element and
|
||||
* output the element
|
||||
*/
|
||||
|
||||
temp |= ((uint16_t)in[i]) >> shift;
|
||||
*out++ = temp & mask;
|
||||
temp = 0;
|
||||
}
|
||||
|
||||
/* add the remaining bits of the current octet to start an element */
|
||||
|
||||
shift = n_bits - shift;
|
||||
temp |= ((uint16_t)in[i]) << shift;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,183 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_convert.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_ntru_convert.h
|
||||
*
|
||||
* Contents: Definitions and declarations for conversion routines
|
||||
* for NTRUEncrypt, including packing, unpacking and others.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NTRU_CRYPTO_NTRU_CONVERT_H
|
||||
#define NTRU_CRYPTO_NTRU_CONVERT_H
|
||||
|
||||
#include "ntru_crypto.h"
|
||||
|
||||
|
||||
/* function declarations */
|
||||
|
||||
/* ntru_bits_2_trits
|
||||
*
|
||||
* Each 3 bits in an array of octets is converted to 2 trits in an array
|
||||
* of trits.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_bits_2_trits(
|
||||
uint8_t const *octets, /* in - pointer to array of octets */
|
||||
uint16_t num_trits, /* in - number of trits to produce */
|
||||
uint8_t *trits); /* out - address for array of trits */
|
||||
|
||||
|
||||
/* ntru_trits_2_bits
|
||||
*
|
||||
* Each 2 trits in an array of trits is converted to 3 bits, and the bits
|
||||
* are packed in an array of octets. A multiple of 3 octets is output.
|
||||
* Any bits in the final octets not derived from trits are zero.
|
||||
*
|
||||
* Returns TRUE if all trits were valid.
|
||||
* Returns FALSE if invalid trits were found.
|
||||
*/
|
||||
|
||||
extern bool
|
||||
ntru_trits_2_bits(
|
||||
uint8_t const *trits, /* in - pointer to array of trits */
|
||||
uint32_t num_trits, /* in - number of trits to convert */
|
||||
uint8_t *octets); /* out - address for array of octets */
|
||||
|
||||
|
||||
/* ntru_coeffs_mod4_2_octets
|
||||
*
|
||||
* Takes an array of coefficients mod 4 and packs the results into an
|
||||
* octet string.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_coeffs_mod4_2_octets(
|
||||
uint16_t num_coeffs, /* in - number of coefficients */
|
||||
uint16_t const *coeffs, /* in - pointer to coefficients */
|
||||
uint8_t *octets); /* out - address for octets */
|
||||
|
||||
|
||||
/* ntru_trits_2_octet
|
||||
*
|
||||
* Packs 5 trits in an octet, where a trit is 0, 1, or 2 (-1).
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_trits_2_octet(
|
||||
uint8_t const *trits, /* in - pointer to trits */
|
||||
uint8_t *octet); /* out - address for octet */
|
||||
|
||||
|
||||
/* ntru_octet_2_trits
|
||||
*
|
||||
* Unpacks an octet to 5 trits, where a trit is 0, 1, or 2 (-1).
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_octet_2_trits(
|
||||
uint8_t octet, /* in - octet to be unpacked */
|
||||
uint8_t *trits); /* out - address for trits */
|
||||
|
||||
|
||||
/* ntru_indices_2_trits
|
||||
*
|
||||
* Converts a list of the nonzero indices of a polynomial into an array of
|
||||
* trits.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_indices_2_trits(
|
||||
uint16_t in_len, /* in - no. of indices */
|
||||
uint16_t const *in, /* in - pointer to list of indices */
|
||||
bool plus1, /* in - if list is +1 coefficients */
|
||||
uint8_t *out); /* out - address of output polynomial */
|
||||
|
||||
|
||||
/* ntru_packed_trits_2_indices
|
||||
*
|
||||
* Unpacks an array of N trits and creates a list of array indices
|
||||
* corresponding to trits = +1, and list of array indices corresponding to
|
||||
* trits = -1.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_packed_trits_2_indices(
|
||||
uint8_t const *in, /* in - pointer to packed-trit octets */
|
||||
uint16_t num_trits, /* in - no. of packed trits */
|
||||
uint16_t *indices_plus1, /* out - address for indices of +1 trits */
|
||||
uint16_t *indices_minus1); /* out - address for indices of -1 trits */
|
||||
|
||||
|
||||
/* ntru_indices_2_packed_trits
|
||||
*
|
||||
* Takes a list of array indices corresponding to elements whose values
|
||||
* are +1 or -1, and packs the N-element array of trits described by these
|
||||
* lists into octets, 5 trits per octet.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_indices_2_packed_trits(
|
||||
uint16_t const *indices, /* in - pointer to indices */
|
||||
uint16_t num_plus1, /* in - no. of indices for +1 trits */
|
||||
uint16_t num_minus1, /* in - no. of indices for -1 trits */
|
||||
uint16_t num_trits, /* in - N, no. of trits in array */
|
||||
uint8_t *buf, /* in - temp buf, N octets */
|
||||
uint8_t *out); /* out - address for packed octets */
|
||||
|
||||
|
||||
/* ntru_elements_2_octets
|
||||
*
|
||||
* Packs an array of n-bit elements into an array of
|
||||
* ((in_len * n_bits) + 7) / 8 octets, 8 < n_bits < 16.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_elements_2_octets(
|
||||
uint16_t in_len, /* in - no. of elements to be packed */
|
||||
uint16_t const *in, /* in - ptr to elements to be packed */
|
||||
uint8_t n_bits, /* in - no. of bits in input element */
|
||||
uint8_t *out); /* out - addr for output octets */
|
||||
|
||||
|
||||
/* ntru_octets_2_elements
|
||||
*
|
||||
* Unpacks an octet string into an array of ((in_len * 8) / n_bits)
|
||||
* n-bit elements, 8 < n < 16. Any extra bits are discarded.
|
||||
*/
|
||||
|
||||
extern void
|
||||
ntru_octets_2_elements(
|
||||
uint16_t in_len, /* in - no. of octets to be unpacked */
|
||||
uint8_t const *in, /* in - ptr to octets to be unpacked */
|
||||
uint8_t n_bits, /* in - no. of bits in output element */
|
||||
uint16_t *out); /* out - addr for output elements */
|
||||
|
||||
|
||||
#endif /* NTRU_CRYPTO_NTRU_CONVERT_H */
|
||||
|
||||
|
||||
@ -1,374 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_encrypt.c 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_ntru_encrypt.c
|
||||
*
|
||||
* Contents: Routines implementing NTRUEncrypt encryption and decryption and
|
||||
* key generation.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "ntru_crypto.h"
|
||||
#include "ntru_crypto_ntru_encrypt_key.h"
|
||||
#include "ntru_crypto_ntru_convert.h"
|
||||
#include "ntru_crypto_ntru_poly.h"
|
||||
|
||||
#include "ntru_param_set.h"
|
||||
#include "ntru_trits.h"
|
||||
#include "ntru_poly.h"
|
||||
|
||||
/* ntru_crypto_ntru_encrypt
|
||||
*
|
||||
* Implements NTRU encryption (SVES) for the parameter set specified in
|
||||
* the public key blob.
|
||||
*
|
||||
* 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 ciphertext buffer (ct) may be
|
||||
* queried by invoking this function with ct = NULL. In this case, no
|
||||
* encryption is performed, NTRU_OK is returned, and the required minimum
|
||||
* size for ct is returned in ct_len.
|
||||
*
|
||||
* When ct != NULL, at invocation *ct_len must be the size of the ct buffer.
|
||||
* Upon return it is the actual size of the ciphertext.
|
||||
*
|
||||
* Returns NTRU_OK if successful.
|
||||
* 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
|
||||
ntru_crypto_ntru_encrypt(
|
||||
ntru_drbg_t *drbg, /* in - handle of DRBG */
|
||||
uint16_t pubkey_blob_len, /* in - no. of octets in public key
|
||||
blob */
|
||||
uint8_t const *pubkey_blob, /* in - pointer to public key */
|
||||
uint16_t pt_len, /* in - no. of octets in plaintext */
|
||||
uint8_t const *pt, /* in - pointer to plaintext */
|
||||
uint16_t *ct_len, /* in/out - no. of octets in ct, addr for
|
||||
no. of octets in ciphertext */
|
||||
uint8_t *ct) /* out - address for ciphertext */
|
||||
{
|
||||
ntru_param_set_t *params = NULL;
|
||||
uint8_t const *pubkey_packed = NULL;
|
||||
uint8_t pubkey_pack_type = 0x00;
|
||||
uint16_t packed_ct_len;
|
||||
size_t scratch_buf_len;
|
||||
uint32_t dr;
|
||||
uint32_t dr1 = 0;
|
||||
uint32_t dr2 = 0;
|
||||
uint32_t dr3 = 0;
|
||||
uint16_t ring_mult_tmp_len;
|
||||
int16_t m1;
|
||||
uint16_t *scratch_buf = NULL;
|
||||
uint16_t *ringel_buf = NULL;
|
||||
uint8_t *b_buf = NULL;
|
||||
uint8_t *tmp_buf = NULL;
|
||||
bool msg_rep_good = FALSE;
|
||||
hash_algorithm_t hash_algid;
|
||||
uint16_t mprime_len = 0;
|
||||
uint16_t mod_q_mask;
|
||||
uint32_t result = NTRU_OK;
|
||||
ntru_trits_t *mask;
|
||||
uint8_t *mask_trits;
|
||||
chunk_t seed;
|
||||
ntru_poly_t *r_poly;
|
||||
|
||||
/* check for bad parameters */
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
if (!ntru_crypto_ntru_encrypt_key_parse(TRUE /* pubkey */, pubkey_blob_len,
|
||||
pubkey_blob, &pubkey_pack_type,
|
||||
NULL, ¶ms, &pubkey_packed,
|
||||
NULL))
|
||||
{
|
||||
return NTRU_BAD_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
/* return the ciphertext size if requested */
|
||||
|
||||
packed_ct_len = (params->N * params->q_bits + 7) >> 3;
|
||||
if (!ct)
|
||||
{
|
||||
*ct_len = packed_ct_len;
|
||||
return NTRU_OK;
|
||||
}
|
||||
|
||||
/* check the ciphertext buffer size */
|
||||
|
||||
if (*ct_len < packed_ct_len)
|
||||
{
|
||||
return NTRU_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* check the plaintext length */
|
||||
|
||||
if (pt_len > params->m_len_max)
|
||||
{
|
||||
return NTRU_BAD_LENGTH;
|
||||
}
|
||||
|
||||
/* allocate memory for all operations */
|
||||
|
||||
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
|
||||
{
|
||||
ring_mult_tmp_len = params->N; /* N 16-bit word buffer */
|
||||
dr = params->dF_r;
|
||||
}
|
||||
scratch_buf_len = (ring_mult_tmp_len << 1) +
|
||||
/* X-byte temp buf for ring mult and
|
||||
other intermediate results */
|
||||
(params->N << 1) + /* 2N-byte buffer for ring elements
|
||||
and overflow from temp buffer */
|
||||
(dr << 2) + /* buffer for r indices */
|
||||
params->sec_strength_len;
|
||||
/* buffer for b */
|
||||
scratch_buf = malloc(scratch_buf_len);
|
||||
if (!scratch_buf)
|
||||
{
|
||||
return NTRU_OUT_OF_MEMORY;
|
||||
}
|
||||
ringel_buf = scratch_buf + ring_mult_tmp_len;
|
||||
b_buf = (uint8_t *)(ringel_buf + params->N);
|
||||
tmp_buf = (uint8_t *)scratch_buf;
|
||||
|
||||
/* set hash algorithm based on security strength */
|
||||
hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256;
|
||||
|
||||
/* set constants */
|
||||
mod_q_mask = params->q - 1;
|
||||
|
||||
/* loop until a message representative with proper weight is achieved */
|
||||
|
||||
do {
|
||||
uint8_t *ptr = tmp_buf;
|
||||
|
||||
/* get b */
|
||||
if (drbg->generate(drbg, params->sec_strength_len * BITS_PER_BYTE,
|
||||
params->sec_strength_len, b_buf))
|
||||
{
|
||||
result = NTRU_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = NTRU_FAIL;
|
||||
}
|
||||
|
||||
if (result == NTRU_OK)
|
||||
{
|
||||
|
||||
/* form sData (OID || m || b || hTrunc) */
|
||||
memcpy(ptr, params->oid, 3);
|
||||
ptr += 3;
|
||||
memcpy(ptr, pt, pt_len);
|
||||
ptr += pt_len;
|
||||
memcpy(ptr, b_buf, params->sec_strength_len);
|
||||
ptr += params->sec_strength_len;
|
||||
memcpy(ptr, pubkey_packed, params->sec_strength_len);
|
||||
ptr += params->sec_strength_len;
|
||||
|
||||
DBG2(DBG_LIB, "generate polynomial r");
|
||||
|
||||
seed = chunk_create(tmp_buf, ptr - tmp_buf);
|
||||
r_poly = ntru_poly_create_from_seed(hash_algid, seed, params->c_bits,
|
||||
params->N, params->q,
|
||||
params->dF_r, params->dF_r,
|
||||
params->is_product_form);
|
||||
if (!r_poly)
|
||||
{
|
||||
result = NTRU_MGF1_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == NTRU_OK)
|
||||
{
|
||||
uint16_t pubkey_packed_len;
|
||||
|
||||
/* unpack the public key */
|
||||
assert(pubkey_pack_type == NTRU_KEY_PACKED_COEFFICIENTS);
|
||||
pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
|
||||
ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
|
||||
params->q_bits, ringel_buf);
|
||||
|
||||
/* form R = h * r */
|
||||
r_poly->ring_mult(r_poly, ringel_buf, ringel_buf);
|
||||
r_poly->destroy(r_poly);
|
||||
|
||||
/* form R mod 4 */
|
||||
ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf);
|
||||
|
||||
/* form mask */
|
||||
seed = chunk_create(tmp_buf, (params->N + 3)/4);
|
||||
mask = ntru_trits_create(params->N, hash_algid, seed);
|
||||
if (!mask)
|
||||
{
|
||||
result = NTRU_MGF1_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
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 +
|
||||
params->m_len_max + 2);
|
||||
uint16_t i;
|
||||
|
||||
/* form the padded message M */
|
||||
ptr = M_buf;
|
||||
memcpy(ptr, b_buf, params->sec_strength_len);
|
||||
ptr += params->sec_strength_len;
|
||||
if (params->m_len_len == 2)
|
||||
*ptr++ = (uint8_t)((pt_len >> 8) & 0xff);
|
||||
*ptr++ = (uint8_t)(pt_len & 0xff);
|
||||
memcpy(ptr, pt, pt_len);
|
||||
ptr += pt_len;
|
||||
|
||||
/* add an extra zero byte in case without it the bit string
|
||||
* is not a multiple of 3 bits and therefore might not be
|
||||
* able to produce enough trits
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
--mprime_len;
|
||||
}
|
||||
|
||||
ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf);
|
||||
mask_trits = mask->get_trits(mask);
|
||||
|
||||
/* form the msg representative m' by adding Mtrin to mask, mod p */
|
||||
if (params->is_product_form)
|
||||
{
|
||||
m1 = 0;
|
||||
for (i = 0; i < mprime_len; i++)
|
||||
{
|
||||
tmp_buf[i] = mask_trits[i] + Mtrin_buf[i];
|
||||
if (tmp_buf[i] >= 3)
|
||||
{
|
||||
tmp_buf[i] -= 3;
|
||||
}
|
||||
if (tmp_buf[i] == 1)
|
||||
{
|
||||
++m1;
|
||||
}
|
||||
else if (tmp_buf[i] == 2)
|
||||
{
|
||||
--m1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < mprime_len; i++)
|
||||
{
|
||||
tmp_buf[i] = mask_trits[i] + Mtrin_buf[i];
|
||||
if (tmp_buf[i] >= 3)
|
||||
{
|
||||
tmp_buf[i] -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
mask->destroy(mask);
|
||||
|
||||
/* check that message representative meets minimum weight
|
||||
* requirements
|
||||
*/
|
||||
|
||||
if (params->is_product_form)
|
||||
msg_rep_good = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) :
|
||||
(bool)( m1 <= params->min_msg_rep_wt);
|
||||
else
|
||||
msg_rep_good = ntru_poly_check_min_weight(mprime_len, tmp_buf,
|
||||
params->min_msg_rep_wt);
|
||||
}
|
||||
} while ((result == NTRU_OK) && !msg_rep_good);
|
||||
|
||||
if (result == NTRU_OK)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
/* form ciphertext e by adding m' to R mod q */
|
||||
|
||||
for (i = 0; i < mprime_len; i++) {
|
||||
if (tmp_buf[i] == 1)
|
||||
ringel_buf[i] = (ringel_buf[i] + 1) & mod_q_mask;
|
||||
else if (tmp_buf[i] == 2)
|
||||
ringel_buf[i] = (ringel_buf[i] - 1) & mod_q_mask;
|
||||
}
|
||||
if (params->is_product_form)
|
||||
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;
|
||||
}
|
||||
@ -1,187 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_encrypt_key.c 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_ntru_encrypt_key.c
|
||||
*
|
||||
* Contents: Routines for exporting and importing public and private keys
|
||||
* for NTRUEncrypt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "ntru_crypto_ntru_encrypt_key.h"
|
||||
|
||||
|
||||
/* ntru_crypto_ntru_encrypt_key_parse
|
||||
*
|
||||
* Parses an NTRUEncrypt key blob.
|
||||
* If the blob is not corrupt, returns packing types for public and private
|
||||
* keys, a pointer to the parameter set, a pointer to the public key, and
|
||||
* a pointer to the private key if it exists.
|
||||
*
|
||||
* Returns TRUE if successful.
|
||||
* Returns FALSE if the blob is invalid.
|
||||
*/
|
||||
|
||||
bool
|
||||
ntru_crypto_ntru_encrypt_key_parse(
|
||||
bool pubkey_parse, /* in - if parsing pubkey
|
||||
blob */
|
||||
uint16_t key_blob_len, /* in - no. octets in key
|
||||
blob */
|
||||
uint8_t const *key_blob, /* in - pointer to key blob */
|
||||
uint8_t *pubkey_pack_type, /* out - addr for pubkey
|
||||
packing type */
|
||||
uint8_t *privkey_pack_type, /* out - addr for privkey
|
||||
packing type */
|
||||
ntru_param_set_t **params, /* out - addr for ptr to
|
||||
parameter set */
|
||||
uint8_t const **pubkey, /* out - addr for ptr to
|
||||
packed pubkey */
|
||||
uint8_t const **privkey) /* out - addr for ptr to
|
||||
packed privkey */
|
||||
{
|
||||
uint8_t tag;
|
||||
|
||||
/* parse key blob based on tag */
|
||||
tag = key_blob[0];
|
||||
switch (tag) {
|
||||
case NTRU_PUBKEY_TAG:
|
||||
if (!pubkey_parse)
|
||||
return FALSE;
|
||||
break;
|
||||
case NTRU_PRIVKEY_DEFAULT_TAG:
|
||||
case NTRU_PRIVKEY_TRITS_TAG:
|
||||
case NTRU_PRIVKEY_INDICES_TAG:
|
||||
assert(privkey_pack_type);
|
||||
assert(privkey);
|
||||
if (pubkey_parse)
|
||||
return FALSE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
case NTRU_PUBKEY_TAG:
|
||||
case NTRU_PRIVKEY_DEFAULT_TAG:
|
||||
case NTRU_PRIVKEY_TRITS_TAG:
|
||||
case NTRU_PRIVKEY_INDICES_TAG:
|
||||
|
||||
/* Version 0:
|
||||
* byte 0: tag
|
||||
* byte 1: no. of octets in OID
|
||||
* bytes 2-4: OID
|
||||
* bytes 5- : packed pubkey
|
||||
* [packed privkey]
|
||||
*/
|
||||
|
||||
{
|
||||
ntru_param_set_t *p = NULL;
|
||||
uint16_t pubkey_packed_len;
|
||||
|
||||
/* check OID length and minimum blob length for tag and OID */
|
||||
|
||||
if ((key_blob_len < 5) || (key_blob[1] != 3))
|
||||
return FALSE;
|
||||
|
||||
/* get a pointer to the parameter set corresponding to the OID */
|
||||
p = ntru_param_set_get_by_oid(key_blob + 2);
|
||||
if (!p)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* check blob length and assign pointers to blob fields */
|
||||
|
||||
pubkey_packed_len = (p->N * p->q_bits + 7) / 8;
|
||||
if (pubkey_parse) { /* public-key parsing */
|
||||
if (key_blob_len != 5 + pubkey_packed_len)
|
||||
return FALSE;
|
||||
|
||||
*pubkey = key_blob + 5;
|
||||
|
||||
} else { /* private-key parsing */
|
||||
uint16_t privkey_packed_len;
|
||||
uint16_t privkey_packed_trits_len = (p->N + 4) / 5;
|
||||
uint16_t privkey_packed_indices_len;
|
||||
uint16_t dF;
|
||||
|
||||
/* check packing type for product-form private keys */
|
||||
|
||||
if (p->is_product_form &&
|
||||
(tag == NTRU_PRIVKEY_TRITS_TAG))
|
||||
return FALSE;
|
||||
|
||||
/* set packed-key length for packed indices */
|
||||
|
||||
if (p->is_product_form)
|
||||
dF = (uint16_t)( (p->dF_r & 0xff) + /* df1 */
|
||||
((p->dF_r >> 8) & 0xff) + /* df2 */
|
||||
((p->dF_r >> 16) & 0xff)); /* df3 */
|
||||
else
|
||||
dF = (uint16_t)p->dF_r;
|
||||
privkey_packed_indices_len = ((dF << 1) * p->N_bits + 7) >> 3;
|
||||
|
||||
/* set private-key packing type if defaulted */
|
||||
|
||||
if (tag == NTRU_PRIVKEY_DEFAULT_TAG) {
|
||||
if (p->is_product_form ||
|
||||
(privkey_packed_indices_len <=
|
||||
privkey_packed_trits_len))
|
||||
tag = NTRU_PRIVKEY_INDICES_TAG;
|
||||
else
|
||||
tag = NTRU_PRIVKEY_TRITS_TAG;
|
||||
}
|
||||
|
||||
if (tag == NTRU_PRIVKEY_TRITS_TAG)
|
||||
privkey_packed_len = privkey_packed_trits_len;
|
||||
else
|
||||
privkey_packed_len = privkey_packed_indices_len;
|
||||
|
||||
if (key_blob_len != 5 + pubkey_packed_len + privkey_packed_len)
|
||||
return FALSE;
|
||||
|
||||
*pubkey = key_blob + 5;
|
||||
*privkey = *pubkey + pubkey_packed_len;
|
||||
*privkey_pack_type = (tag == NTRU_PRIVKEY_TRITS_TAG) ?
|
||||
NTRU_KEY_PACKED_TRITS :
|
||||
NTRU_KEY_PACKED_INDICES;
|
||||
}
|
||||
|
||||
/* return parameter set pointer */
|
||||
|
||||
*pubkey_pack_type = NTRU_KEY_PACKED_COEFFICIENTS;
|
||||
*params = p;
|
||||
}
|
||||
default:
|
||||
break; /* can't get here */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_cencrypt_key.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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H
|
||||
#define NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H
|
||||
|
||||
#include "ntru_crypto_ntru_convert.h"
|
||||
|
||||
#include "ntru_param_set.h"
|
||||
|
||||
/* function declarations */
|
||||
|
||||
|
||||
/* ntru_crypto_ntru_encrypt_key_parse
|
||||
*
|
||||
* Parses an NTRUEncrypt key blob.
|
||||
* If the blob is not corrupt, returns packing types for public and private
|
||||
* keys, a pointer to the parameter set, a pointer to the public key, and
|
||||
* a pointer to the private key if it exists.
|
||||
*
|
||||
* Returns TRUE if successful.
|
||||
* Returns FALSE if the blob is invalid.
|
||||
*/
|
||||
|
||||
extern bool
|
||||
ntru_crypto_ntru_encrypt_key_parse(
|
||||
bool pubkey_parse, /* in - if parsing pubkey
|
||||
blob */
|
||||
uint16_t key_blob_len, /* in - no. octets in key
|
||||
blob */
|
||||
uint8_t const *key_blob, /* in - pointer to key blob */
|
||||
uint8_t *pubkey_pack_type, /* out - addr for pubkey
|
||||
packing type */
|
||||
uint8_t *privkey_pack_type, /* out - addr for privkey
|
||||
packing type */
|
||||
ntru_param_set_t **params, /* out - addr for ptr to
|
||||
parameter set */
|
||||
uint8_t const **pubkey, /* out - addr for ptr to
|
||||
packed pubkey */
|
||||
uint8_t const **privkey); /* out - addr for ptr to
|
||||
packed privkey */
|
||||
|
||||
#endif /* NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H */
|
||||
@ -1,53 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_poly.c 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ntru_crypto_ntru_poly.h"
|
||||
|
||||
/* ntru_poly_check_min_weight
|
||||
*
|
||||
* Checks that the number of 0, +1, and -1 trinary ring elements meet or exceed
|
||||
* a minimum weight.
|
||||
*/
|
||||
|
||||
bool
|
||||
ntru_poly_check_min_weight(
|
||||
uint16_t num_els, /* in - degree of polynomial */
|
||||
uint8_t *ringels, /* in - pointer to trinary ring elements */
|
||||
uint16_t min_wt) /* in - minimum weight */
|
||||
{
|
||||
uint16_t wt[3];
|
||||
uint16_t i;
|
||||
|
||||
wt[0] = wt[1] = wt[2] = 0;
|
||||
for (i = 0; i < num_els; i++) {
|
||||
++wt[ringels[i]];
|
||||
}
|
||||
if ((wt[0] < min_wt) || (wt[1] < min_wt) || (wt[2] < min_wt)) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
/******************************************************************************
|
||||
* NTRU Cryptography Reference Source Code
|
||||
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
|
||||
*
|
||||
* ntru_crypto_ntru_poly.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_ntru_poly.h
|
||||
*
|
||||
* Contents: Public header file for generating and operating on polynomials
|
||||
* in the NTRU algorithm.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef NTRU_CRYPTO_NTRU_POLY_H
|
||||
#define NTRU_CRYPTO_NTRU_POLY_H
|
||||
|
||||
|
||||
#include "ntru_crypto.h"
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
|
||||
/* function declarations */
|
||||
|
||||
/* ntru_poly_check_min_weight
|
||||
*
|
||||
* Checks that the number of 0, +1, and -1 trinary ring elements meet or exceed
|
||||
* a minimum weight.
|
||||
*/
|
||||
|
||||
extern bool
|
||||
ntru_poly_check_min_weight(
|
||||
uint16_t num_els, /* in - degree of polynomial */
|
||||
uint8_t *ringels, /* in - pointer to trinary ring elements */
|
||||
uint16_t min_wt); /* in - minimum weight */
|
||||
|
||||
#endif /* NTRU_CRYPTO_NTRU_POLY_H */
|
||||
@ -67,6 +67,10 @@ struct private_ntru_drbg_t {
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -180,13 +184,23 @@ METHOD(ntru_drbg_t, generate, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(ntru_drbg_t, get_ref, ntru_drbg_t*,
|
||||
private_ntru_drbg_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(ntru_drbg_t, destroy, void,
|
||||
private_ntru_drbg_t *this)
|
||||
{
|
||||
this->hmac->destroy(this->hmac);
|
||||
chunk_clear(&this->key);
|
||||
chunk_clear(&this->value);
|
||||
free(this);
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->hmac->destroy(this->hmac);
|
||||
chunk_clear(&this->key);
|
||||
chunk_clear(&this->value);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -238,6 +252,7 @@ ntru_drbg_t *ntru_drbg_create(u_int32_t strength, chunk_t pers_str,
|
||||
.get_strength = _get_strength,
|
||||
.reseed = _reseed,
|
||||
.generate = _generate,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.strength = strength,
|
||||
@ -247,6 +262,7 @@ ntru_drbg_t *ntru_drbg_create(u_int32_t strength, chunk_t pers_str,
|
||||
.value = chunk_alloc(hmac->get_block_size(hmac)),
|
||||
.max_requests = max_requests,
|
||||
.reseed_counter = 1,
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
memset(this->key.ptr, 0x00, this->key.len);
|
||||
|
||||
@ -57,6 +57,13 @@ struct ntru_drbg_t {
|
||||
bool (*generate)(ntru_drbg_t *this, u_int32_t strength, u_int32_t len,
|
||||
u_int8_t *out);
|
||||
|
||||
/**
|
||||
* Get a reference on an ntru_drbg_t object increasing the count by one
|
||||
*
|
||||
* @return reference to the ntru_drbg_t object
|
||||
*/
|
||||
ntru_drbg_t* (*get_ref)(ntru_drbg_t *this);
|
||||
|
||||
/**
|
||||
* Uninstantiate and destroy the DRBG object
|
||||
*/
|
||||
|
||||
@ -19,8 +19,6 @@
|
||||
#include "ntru_private_key.h"
|
||||
#include "ntru_public_key.h"
|
||||
|
||||
#include "ntru_crypto/ntru_crypto.h"
|
||||
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
@ -80,11 +78,6 @@ struct private_ntru_ke_t {
|
||||
*/
|
||||
ntru_private_key_t *privkey;
|
||||
|
||||
/**
|
||||
* NTRU Public Key Encoding
|
||||
*/
|
||||
chunk_t pubkey_enc;
|
||||
|
||||
/**
|
||||
* NTRU encrypted shared secret
|
||||
*/
|
||||
@ -140,11 +133,9 @@ METHOD(diffie_hellman_t, get_my_public_value, void,
|
||||
return;
|
||||
}
|
||||
this->pubkey = this->privkey->get_public_key(this->privkey);
|
||||
this->pubkey_enc = this->pubkey->get_encoding(this->pubkey);
|
||||
this->pubkey_enc = chunk_clone(this->pubkey_enc);
|
||||
DBG3(DBG_LIB, "NTRU public key: %B", &this->pubkey_enc);
|
||||
}
|
||||
*value = chunk_clone(this->pubkey_enc);
|
||||
*value = chunk_clone(this->pubkey->get_encoding(this->pubkey));
|
||||
DBG3(DBG_LIB, "NTRU public key: %B", value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,8 +156,6 @@ METHOD(diffie_hellman_t, get_shared_secret, status_t,
|
||||
METHOD(diffie_hellman_t, set_other_public_value, void,
|
||||
private_ntru_ke_t *this, chunk_t value)
|
||||
{
|
||||
u_int16_t ciphertext_len;
|
||||
|
||||
if (this->privkey)
|
||||
{
|
||||
/* initiator decrypting shared secret */
|
||||
@ -187,23 +176,24 @@ METHOD(diffie_hellman_t, set_other_public_value, void,
|
||||
}
|
||||
else
|
||||
{
|
||||
ntru_public_key_t *pubkey;
|
||||
|
||||
/* responder generating and encrypting the shared secret */
|
||||
this->responder = TRUE;
|
||||
|
||||
/* check the NTRU public key format */
|
||||
if (value.len < 5 ||
|
||||
value.ptr[0] != NTRU_PUBKEY_TAG ||
|
||||
value.ptr[1] != NTRU_OID_LEN)
|
||||
DBG3(DBG_LIB, "NTRU public key: %B", &value);
|
||||
pubkey = ntru_public_key_create_from_data(this->drbg, value);
|
||||
if (!pubkey)
|
||||
{
|
||||
DBG1(DBG_LIB, "received NTRU public key with invalid header");
|
||||
return;
|
||||
}
|
||||
if (!memeq(value.ptr + 2, this->param_set->oid, NTRU_OID_LEN))
|
||||
if (pubkey->get_id(pubkey) != this->param_set->id)
|
||||
{
|
||||
DBG1(DBG_LIB, "received NTRU public key with wrong OID");
|
||||
DBG1(DBG_LIB, "received NTRU public key with wrong OUI");
|
||||
pubkey->destroy(pubkey);
|
||||
return;
|
||||
}
|
||||
this->pubkey_enc = chunk_clone(value);
|
||||
this->pubkey = pubkey;
|
||||
|
||||
/* shared secret size is chosen as twice the cryptographical strength */
|
||||
this->shared_secret = chunk_alloc(2 * this->strength / BITS_PER_BYTE);
|
||||
@ -218,25 +208,10 @@ METHOD(diffie_hellman_t, set_other_public_value, void,
|
||||
}
|
||||
this->computed = TRUE;
|
||||
|
||||
/* determine the size of the ciphertext */
|
||||
if (ntru_crypto_ntru_encrypt(this->drbg,
|
||||
this->pubkey_enc.len, this->pubkey_enc.ptr,
|
||||
this->shared_secret.len, this->shared_secret.ptr,
|
||||
&ciphertext_len, NULL) != NTRU_OK)
|
||||
{
|
||||
DBG1(DBG_LIB, "error determining ciphertext size");
|
||||
return;
|
||||
}
|
||||
this->ciphertext = chunk_alloc(ciphertext_len);
|
||||
|
||||
/* encrypt the shared secret */
|
||||
if (ntru_crypto_ntru_encrypt(this->drbg,
|
||||
this->pubkey_enc.len, this->pubkey_enc.ptr,
|
||||
this->shared_secret.len, this->shared_secret.ptr,
|
||||
&ciphertext_len, this->ciphertext.ptr) != NTRU_OK)
|
||||
if (!pubkey->encrypt(pubkey, this->shared_secret, &this->ciphertext))
|
||||
{
|
||||
DBG1(DBG_LIB, "NTRU encryption of shared secret failed");
|
||||
chunk_free(&this->ciphertext);
|
||||
return;
|
||||
}
|
||||
DBG3(DBG_LIB, "NTRU ciphertext: %B", &this->ciphertext);
|
||||
@ -256,7 +231,6 @@ METHOD(diffie_hellman_t, destroy, void,
|
||||
DESTROY_IF(this->pubkey);
|
||||
this->drbg->destroy(this->drbg);
|
||||
this->entropy->destroy(this->entropy);
|
||||
chunk_free(&this->pubkey_enc);
|
||||
chunk_free(&this->ciphertext);
|
||||
chunk_clear(&this->shared_secret);
|
||||
free(this);
|
||||
|
||||
@ -116,4 +116,3 @@ ntru_param_set_t* ntru_param_set_get_by_id(ntru_param_set_id_t id);
|
||||
ntru_param_set_t* ntru_param_set_get_by_oid(uint8_t const *oid);
|
||||
|
||||
#endif /** NTRU_PARAM_SET_H_ @}*/
|
||||
|
||||
|
||||
@ -18,8 +18,7 @@
|
||||
#include "ntru_private_key.h"
|
||||
#include "ntru_trits.h"
|
||||
#include "ntru_poly.h"
|
||||
|
||||
#include "ntru_crypto/ntru_crypto_ntru_convert.h"
|
||||
#include "ntru_convert.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <utils/test.h>
|
||||
@ -56,12 +55,23 @@ struct private_ntru_private_key_t {
|
||||
*/
|
||||
chunk_t encoding;
|
||||
|
||||
/**
|
||||
* Deterministic Random Bit Generator
|
||||
*/
|
||||
ntru_drbg_t *drbg;
|
||||
|
||||
};
|
||||
|
||||
METHOD(ntru_private_key_t, get_id, ntru_param_set_id_t,
|
||||
private_ntru_private_key_t *this)
|
||||
{
|
||||
return this->params->id;
|
||||
}
|
||||
|
||||
METHOD(ntru_private_key_t, get_public_key, ntru_public_key_t*,
|
||||
private_ntru_private_key_t *this)
|
||||
{
|
||||
return ntru_public_key_create(this->params, this->pubkey);
|
||||
return ntru_public_key_create(this->drbg, this->params, this->pubkey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,9 +155,10 @@ METHOD(ntru_private_key_t, get_encoding, chunk_t,
|
||||
* @param min_wt minimum weight
|
||||
* @return TRUE if minimum weight met or exceeded
|
||||
*/
|
||||
static bool check_min_weight(uint16_t N, uint8_t *t, uint16_t min_wt)
|
||||
bool ntru_check_min_weight(uint16_t N, uint8_t *t, uint16_t min_wt)
|
||||
{
|
||||
uint16_t wt[3];
|
||||
bool success;
|
||||
int i;
|
||||
|
||||
wt[0] = wt[1] = wt[2] = 0;
|
||||
@ -156,8 +167,12 @@ static bool check_min_weight(uint16_t N, uint8_t *t, uint16_t min_wt)
|
||||
{
|
||||
++wt[t[i]];
|
||||
}
|
||||
success = (wt[0] >= min_wt) && (wt[1] >= min_wt) && (wt[2] >= min_wt);
|
||||
|
||||
return (wt[0] >= min_wt) && (wt[1] >= min_wt) && (wt[2] >= min_wt);
|
||||
DBG2(DBG_LIB, "minimum weight = %u, so -1: %u, 0: %u, +1: %u is %sok",
|
||||
min_wt, wt[2], wt[0], wt[1], success ? "" : "not ");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(ntru_private_key_t, decrypt, bool,
|
||||
@ -172,7 +187,7 @@ METHOD(ntru_private_key_t, decrypt, bool,
|
||||
chunk_t seed = chunk_empty;
|
||||
ntru_trits_t *mask;
|
||||
ntru_poly_t *r_poly;
|
||||
bool success = TRUE;
|
||||
bool msg_rep_good, success = TRUE;
|
||||
int i;
|
||||
|
||||
*plaintext = chunk_empty;
|
||||
@ -252,16 +267,17 @@ METHOD(ntru_private_key_t, decrypt, bool,
|
||||
*/
|
||||
if (this->params->is_product_form)
|
||||
{
|
||||
success = (abs(m1) <= this->params->min_msg_rep_wt);
|
||||
msg_rep_good = (abs(m1) <= this->params->min_msg_rep_wt);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = check_min_weight(cmprime_len, Mtrin,
|
||||
this->params->min_msg_rep_wt);
|
||||
msg_rep_good = ntru_check_min_weight(cmprime_len, Mtrin,
|
||||
this->params->min_msg_rep_wt);
|
||||
}
|
||||
if (!success)
|
||||
if (!msg_rep_good)
|
||||
{
|
||||
DBG1(DBG_LIB, "decryption failed due to unsufficient minimum weight");
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
/* form cR = e - cm' mod q */
|
||||
@ -397,7 +413,9 @@ METHOD(ntru_private_key_t, decrypt, bool,
|
||||
if (t[i] != t2[i])
|
||||
{
|
||||
DBG1(DBG_LIB, "cR' does not equal cR'");
|
||||
chunk_clear(plaintext);
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
memwipe(t, t_len);
|
||||
@ -414,6 +432,7 @@ METHOD(ntru_private_key_t, destroy, void,
|
||||
private_ntru_private_key_t *this)
|
||||
{
|
||||
DESTROY_IF(this->privkey);
|
||||
this->drbg->destroy(this->drbg);
|
||||
chunk_clear(&this->encoding);
|
||||
free(this->pubkey);
|
||||
free(this);
|
||||
@ -622,7 +641,8 @@ static bool ring_inv(uint16_t *a, uint16_t N, uint16_t q, uint16_t *t,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg, ntru_param_set_t *params)
|
||||
ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg,
|
||||
ntru_param_set_t *params)
|
||||
{
|
||||
private_ntru_private_key_t *this;
|
||||
size_t t_len;
|
||||
@ -635,6 +655,7 @@ ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg, ntru_param_set_t
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_id = _get_id,
|
||||
.get_public_key = _get_public_key,
|
||||
.get_encoding = _get_encoding,
|
||||
.decrypt = _decrypt,
|
||||
@ -642,6 +663,7 @@ ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg, ntru_param_set_t
|
||||
},
|
||||
.params = params,
|
||||
.pubkey = malloc(params->N * sizeof(uint16_t)),
|
||||
.drbg = drbg->get_ref(drbg),
|
||||
);
|
||||
|
||||
/* set hash algorithm and seed length based on security strength */
|
||||
@ -742,4 +764,129 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ntru_private_key_t *ntru_private_key_create_from_data(ntru_drbg_t *drbg,
|
||||
chunk_t data)
|
||||
{
|
||||
private_ntru_private_key_t *this;
|
||||
size_t header_len, pubkey_packed_len, privkey_packed_len;
|
||||
size_t privkey_packed_trits_len, privkey_packed_indices_len;
|
||||
uint8_t *privkey_packed, tag;
|
||||
uint16_t *indices, dF;
|
||||
ntru_param_set_t *params;
|
||||
|
||||
header_len = 2 + NTRU_OID_LEN;
|
||||
|
||||
/* check the NTRU public key header format */
|
||||
if (data.len < header_len ||
|
||||
!(data.ptr[0] == NTRU_PRIVKEY_DEFAULT_TAG ||
|
||||
data.ptr[0] == NTRU_PRIVKEY_TRITS_TAG ||
|
||||
data.ptr[0] == NTRU_PRIVKEY_INDICES_TAG) ||
|
||||
data.ptr[1] != NTRU_OID_LEN)
|
||||
{
|
||||
DBG1(DBG_LIB, "loaded NTRU private key with invalid header");
|
||||
return NULL;
|
||||
}
|
||||
tag = data.ptr[0];
|
||||
params = ntru_param_set_get_by_oid(data.ptr + 2);
|
||||
|
||||
if (!params)
|
||||
{
|
||||
DBG1(DBG_LIB, "loaded NTRU private key with unknown OID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pubkey_packed_len = (params->N * params->q_bits + 7) / 8;
|
||||
privkey_packed_trits_len = (params->N + 4) / 5;
|
||||
|
||||
/* check packing type for product-form private keys */
|
||||
if (params->is_product_form && tag == NTRU_PRIVKEY_TRITS_TAG)
|
||||
{
|
||||
DBG1(DBG_LIB, "a product-form NTRU private key cannot be trits-encoded");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set packed-key length for packed indices */
|
||||
if (params->is_product_form)
|
||||
{
|
||||
dF = (uint16_t)((params->dF_r & 0xff) + /* df1 */
|
||||
((params->dF_r >> 8) & 0xff) + /* df2 */
|
||||
((params->dF_r >> 16) & 0xff)); /* df3 */
|
||||
}
|
||||
else
|
||||
{
|
||||
dF = (uint16_t)params->dF_r;
|
||||
}
|
||||
privkey_packed_indices_len = (2 * dF * params->N_bits + 7) / 8;
|
||||
|
||||
/* set private-key packing type if defaulted */
|
||||
if (tag == NTRU_PRIVKEY_DEFAULT_TAG)
|
||||
{
|
||||
if (params->is_product_form ||
|
||||
privkey_packed_indices_len <= privkey_packed_trits_len)
|
||||
{
|
||||
tag = NTRU_PRIVKEY_INDICES_TAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag = NTRU_PRIVKEY_TRITS_TAG;
|
||||
}
|
||||
}
|
||||
privkey_packed_len = (tag == NTRU_PRIVKEY_TRITS_TAG) ?
|
||||
privkey_packed_trits_len : privkey_packed_indices_len;
|
||||
|
||||
if (data.len < header_len + pubkey_packed_len + privkey_packed_len)
|
||||
{
|
||||
DBG1(DBG_LIB, "loaded NTRU private key with wrong packed key size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_id = _get_id,
|
||||
.get_public_key = _get_public_key,
|
||||
.get_encoding = _get_encoding,
|
||||
.decrypt = _decrypt,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.params = params,
|
||||
.pubkey = malloc(params->N * sizeof(uint16_t)),
|
||||
.encoding = chunk_clone(data),
|
||||
.drbg = drbg->get_ref(drbg),
|
||||
);
|
||||
|
||||
/* unpack the encoded public key */
|
||||
ntru_octets_2_elements(pubkey_packed_len, data.ptr + header_len,
|
||||
params->q_bits, this->pubkey);
|
||||
|
||||
/* allocate temporary memory for indices */
|
||||
indices = malloc(2 * dF * sizeof(uint16_t));
|
||||
|
||||
/* unpack the private key */
|
||||
privkey_packed = data.ptr + header_len + pubkey_packed_len;
|
||||
if (tag == NTRU_PRIVKEY_TRITS_TAG)
|
||||
{
|
||||
ntru_packed_trits_2_indices(privkey_packed, params->N,
|
||||
indices, indices + dF);
|
||||
}
|
||||
else
|
||||
{
|
||||
ntru_octets_2_elements(privkey_packed_indices_len, privkey_packed,
|
||||
params->N_bits, indices);
|
||||
}
|
||||
this->privkey = ntru_poly_create_from_data(indices, params->N, params->q,
|
||||
params->dF_r, params->dF_r,
|
||||
params->is_product_form);
|
||||
|
||||
/* cleanup */
|
||||
memwipe(indices, 2 * dF * sizeof(uint16_t));
|
||||
free(indices);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_private_key_create);
|
||||
|
||||
EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_private_key_create_from_data);
|
||||
|
||||
@ -34,6 +34,12 @@ typedef struct ntru_private_key_t ntru_private_key_t;
|
||||
*/
|
||||
struct ntru_private_key_t {
|
||||
|
||||
/**
|
||||
* Returns NTRU parameter set ID of the private key
|
||||
*
|
||||
* @return NTRU parameter set ID
|
||||
*/
|
||||
ntru_param_set_id_t (*get_id)(ntru_private_key_t *this);
|
||||
|
||||
/**
|
||||
* Returns the NTRU encryption public key as an encoded binary blob
|
||||
@ -73,6 +79,14 @@ struct ntru_private_key_t {
|
||||
*/
|
||||
ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg, ntru_param_set_t *params);
|
||||
|
||||
/**
|
||||
* Creates an NTRU encryption private key from encoding
|
||||
*
|
||||
* @param drbg Deterministic random bit generator
|
||||
* @param data Encoded NTRU private key
|
||||
*/
|
||||
ntru_private_key_t *ntru_private_key_create_from_data(ntru_drbg_t *drbg,
|
||||
chunk_t data);
|
||||
|
||||
#endif /** NTRU_PRIVATE_KEY_H_ @}*/
|
||||
|
||||
|
||||
@ -16,10 +16,12 @@
|
||||
*/
|
||||
|
||||
#include "ntru_public_key.h"
|
||||
|
||||
#include "ntru_crypto/ntru_crypto_ntru_convert.h"
|
||||
#include "ntru_trits.h"
|
||||
#include "ntru_poly.h"
|
||||
#include "ntru_convert.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <utils/test.h>
|
||||
|
||||
typedef struct private_ntru_public_key_t private_ntru_public_key_t;
|
||||
|
||||
@ -47,37 +49,268 @@ struct private_ntru_public_key_t {
|
||||
*/
|
||||
chunk_t encoding;
|
||||
|
||||
/**
|
||||
* Deterministic Random Bit Generator
|
||||
*/
|
||||
ntru_drbg_t *drbg;
|
||||
|
||||
};
|
||||
|
||||
METHOD(ntru_public_key_t, get_id, ntru_param_set_id_t,
|
||||
private_ntru_public_key_t *this)
|
||||
{
|
||||
return this->params->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate NTRU encryption public key encoding
|
||||
*/
|
||||
static void generate_encoding(private_ntru_public_key_t *this)
|
||||
{
|
||||
size_t pubkey_len;
|
||||
u_char *enc;
|
||||
|
||||
/* compute public key length encoded as packed coefficients */
|
||||
pubkey_len = (this->params->N * this->params->q_bits + 7) / 8;
|
||||
|
||||
/* allocate memory for public key encoding */
|
||||
this->encoding = chunk_alloc(2 + NTRU_OID_LEN + pubkey_len);
|
||||
enc = this->encoding.ptr;
|
||||
|
||||
/* format header and packed public key */
|
||||
*enc++ = NTRU_PUBKEY_TAG;
|
||||
*enc++ = NTRU_OID_LEN;
|
||||
memcpy(enc, this->params->oid, NTRU_OID_LEN);
|
||||
enc += NTRU_OID_LEN;
|
||||
ntru_elements_2_octets(this->params->N, this->pubkey,
|
||||
this->params->q_bits, enc);
|
||||
}
|
||||
|
||||
METHOD(ntru_public_key_t, get_encoding, chunk_t,
|
||||
private_ntru_public_key_t *this)
|
||||
{
|
||||
if (!this->encoding.len)
|
||||
{
|
||||
size_t pubkey_len;
|
||||
u_char *enc;
|
||||
|
||||
/* compute public key length encoded as packed coefficients */
|
||||
pubkey_len = (this->params->N * this->params->q_bits + 7) / 8;
|
||||
|
||||
/* allocate memory for public key encoding */
|
||||
this->encoding = chunk_alloc(2 + NTRU_OID_LEN + pubkey_len);
|
||||
enc = this->encoding.ptr;
|
||||
|
||||
/* format header and packed public key */
|
||||
*enc++ = NTRU_PUBKEY_TAG;
|
||||
*enc++ = NTRU_OID_LEN;
|
||||
memcpy(enc, this->params->oid, NTRU_OID_LEN);
|
||||
enc += NTRU_OID_LEN;
|
||||
ntru_elements_2_octets(this->params->N, this->pubkey,
|
||||
this->params->q_bits, enc);
|
||||
}
|
||||
return this->encoding;
|
||||
}
|
||||
|
||||
#define MAX_SEC_STRENGTH_LEN 32 /* bytes */
|
||||
|
||||
/**
|
||||
* Shared with ntru_private_key.c
|
||||
*/
|
||||
extern bool ntru_check_min_weight(uint16_t N, uint8_t *t, uint16_t min_wt);
|
||||
|
||||
METHOD(ntru_public_key_t, encrypt, bool,
|
||||
private_ntru_public_key_t *this, chunk_t plaintext, chunk_t *ciphertext)
|
||||
{
|
||||
hash_algorithm_t hash_algid;
|
||||
size_t t_len, seed1_len, seed2_len;
|
||||
uint16_t *t1, *t = NULL;
|
||||
uint8_t b[MAX_SEC_STRENGTH_LEN];
|
||||
uint8_t *t2, *Mtrin, *M, *mask_trits, *ptr;
|
||||
uint16_t mod_q_mask, mprime_len = 0;
|
||||
int16_t m1;
|
||||
chunk_t seed = chunk_empty;
|
||||
ntru_trits_t *mask;
|
||||
ntru_poly_t *r_poly;
|
||||
bool msg_rep_good, success = FALSE;
|
||||
int i;
|
||||
|
||||
*ciphertext = chunk_empty;
|
||||
|
||||
if (plaintext.len > this->params->m_len_max)
|
||||
{
|
||||
DBG1(DBG_LIB, "plaintext exceeds maximum size");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (this->params->sec_strength_len > MAX_SEC_STRENGTH_LEN)
|
||||
{
|
||||
DBG1(DBG_LIB, "required security strength exceeds %d bits",
|
||||
MAX_SEC_STRENGTH_LEN * BITS_PER_BYTE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* allocate temporary array t */
|
||||
t_len = (sizeof(uint16_t) + 3*sizeof(uint8_t)) * this->params->N;
|
||||
t = malloc(t_len);
|
||||
t1 = t;
|
||||
t2 = (uint8_t *)(t1 + this->params->N);
|
||||
Mtrin = t2 + this->params->N;
|
||||
M = Mtrin + this->params->N;
|
||||
|
||||
/* set hash algorithm based on security strength */
|
||||
hash_algid = (this->params->sec_strength_len <= 20) ? HASH_SHA1 :
|
||||
HASH_SHA256;
|
||||
/* set constants */
|
||||
mod_q_mask = this->params->q - 1;
|
||||
|
||||
/* allocate memory for the larger of the two seeds */
|
||||
seed1_len = (this->params->N + 3)/4;
|
||||
seed2_len = 3 + 2*this->params->sec_strength_len + plaintext.len;
|
||||
seed = chunk_alloc(max(seed1_len, seed2_len));
|
||||
|
||||
/* loop until a message representative with proper weight is achieved */
|
||||
do
|
||||
{
|
||||
if (!this->drbg->generate(this->drbg,
|
||||
this->params->sec_strength_len * BITS_PER_BYTE,
|
||||
this->params->sec_strength_len, b))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* form sData (OID || m || b || hTrunc) */
|
||||
ptr = seed.ptr;
|
||||
memcpy(ptr, this->params->oid, NTRU_OID_LEN);
|
||||
ptr += NTRU_OID_LEN;
|
||||
memcpy(ptr, plaintext.ptr, plaintext.len);
|
||||
ptr += plaintext.len;
|
||||
memcpy(ptr, b, this->params->sec_strength_len);
|
||||
ptr += this->params->sec_strength_len;
|
||||
memcpy(ptr, this->encoding.ptr + 2 + NTRU_OID_LEN,
|
||||
this->params->sec_strength_len);
|
||||
ptr += this->params->sec_strength_len;
|
||||
seed.len = seed2_len;
|
||||
|
||||
DBG2(DBG_LIB, "generate polynomial r");
|
||||
r_poly = ntru_poly_create_from_seed(hash_algid, seed, this->params->c_bits,
|
||||
this->params->N, this->params->q,
|
||||
this->params->dF_r, this->params->dF_r,
|
||||
this->params->is_product_form);
|
||||
if (!r_poly)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* form R = h * r */
|
||||
r_poly->ring_mult(r_poly, this->pubkey, t1);
|
||||
r_poly->destroy(r_poly);
|
||||
|
||||
/* form R mod 4 */
|
||||
ntru_coeffs_mod4_2_octets(this->params->N, t1, seed.ptr);
|
||||
seed.len = seed1_len;
|
||||
|
||||
/* form mask */
|
||||
mask = ntru_trits_create(this->params->N, hash_algid, seed);
|
||||
if (!mask)
|
||||
{
|
||||
DBG1(DBG_LIB, "mask creation failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* form the padded message M */
|
||||
ptr = M;
|
||||
memcpy(ptr, b, this->params->sec_strength_len);
|
||||
ptr += this->params->sec_strength_len;
|
||||
if (this->params->m_len_len == 2)
|
||||
{
|
||||
*ptr++ = (uint8_t)((plaintext.len >> 8) & 0xff);
|
||||
}
|
||||
*ptr++ = (uint8_t)(plaintext.len & 0xff);
|
||||
memcpy(ptr, plaintext.ptr, plaintext.len);
|
||||
ptr += plaintext.len;
|
||||
|
||||
/* add an extra zero byte in case without it the bit string
|
||||
* is not a multiple of 3 bits and therefore might not be
|
||||
* able to produce enough trits
|
||||
*/
|
||||
memset(ptr, 0, this->params->m_len_max - plaintext.len + 2);
|
||||
|
||||
/* convert M to trits (Mbin to Mtrin) */
|
||||
mprime_len = this->params->N;
|
||||
if (this->params->is_product_form)
|
||||
{
|
||||
--mprime_len;
|
||||
}
|
||||
ntru_bits_2_trits(M, mprime_len, Mtrin);
|
||||
mask_trits = mask->get_trits(mask);
|
||||
|
||||
|
||||
/* form the msg representative m' by adding Mtrin to mask, mod p */
|
||||
if (this->params->is_product_form)
|
||||
{
|
||||
m1 = 0;
|
||||
for (i = 0; i < mprime_len; i++)
|
||||
{
|
||||
t2[i] = mask_trits[i] + Mtrin[i];
|
||||
if (t2[i] >= 3)
|
||||
{
|
||||
t2[i] -= 3;
|
||||
}
|
||||
if (t2[i] == 1)
|
||||
{
|
||||
++m1;
|
||||
}
|
||||
else if (t2[i] == 2)
|
||||
{
|
||||
--m1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < mprime_len; i++)
|
||||
{
|
||||
t2[i] = mask_trits[i] + Mtrin[i];
|
||||
if (t2[i] >= 3)
|
||||
{
|
||||
t2[i] -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
mask->destroy(mask);
|
||||
|
||||
/* check that message representative meets minimum weight
|
||||
* requirements
|
||||
*/
|
||||
if (this->params->is_product_form)
|
||||
{
|
||||
msg_rep_good = (abs(m1) <= this->params->min_msg_rep_wt);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_rep_good = ntru_check_min_weight(mprime_len, t2,
|
||||
this->params->min_msg_rep_wt);
|
||||
}
|
||||
}
|
||||
while (!msg_rep_good);
|
||||
|
||||
/* form ciphertext e by adding m' to R mod q */
|
||||
for (i = 0; i < mprime_len; i++)
|
||||
{
|
||||
if (t2[i] == 1)
|
||||
{
|
||||
t1[i] = (t1[i] + 1) & mod_q_mask;
|
||||
}
|
||||
else if (t2[i] == 2)
|
||||
{
|
||||
t1[i] = (t1[i] - 1) & mod_q_mask;
|
||||
}
|
||||
}
|
||||
if (this->params->is_product_form)
|
||||
{
|
||||
t1[i] = (t1[i] - m1) & mod_q_mask;
|
||||
}
|
||||
|
||||
/* pack ciphertext */
|
||||
*ciphertext = chunk_alloc((this->params->N * this->params->q_bits + 7) / 8);
|
||||
ntru_elements_2_octets(this->params->N, t1, this->params->q_bits,
|
||||
ciphertext->ptr);
|
||||
|
||||
memwipe(t, t_len);
|
||||
success = TRUE;
|
||||
|
||||
err:
|
||||
/* cleanup */
|
||||
chunk_clear(&seed);
|
||||
free(t);
|
||||
|
||||
return success;
|
||||
}
|
||||
METHOD(ntru_public_key_t, destroy, void,
|
||||
private_ntru_public_key_t *this)
|
||||
{
|
||||
this->drbg->destroy(this->drbg);
|
||||
chunk_clear(&this->encoding);
|
||||
free(this->pubkey);
|
||||
free(this);
|
||||
@ -86,7 +319,8 @@ METHOD(ntru_public_key_t, destroy, void,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ntru_public_key_t *ntru_public_key_create(ntru_param_set_t *params,
|
||||
ntru_public_key_t *ntru_public_key_create(ntru_drbg_t *drbg,
|
||||
ntru_param_set_t *params,
|
||||
uint16_t *pubkey)
|
||||
{
|
||||
private_ntru_public_key_t *this;
|
||||
@ -94,11 +328,14 @@ ntru_public_key_t *ntru_public_key_create(ntru_param_set_t *params,
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_id = _get_id,
|
||||
.get_encoding = _get_encoding,
|
||||
.encrypt = _encrypt,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.params = params,
|
||||
.pubkey = malloc(params->N * sizeof(uint16_t)),
|
||||
.drbg = drbg->get_ref(drbg),
|
||||
);
|
||||
|
||||
for (i = 0; i < params->N; i++)
|
||||
@ -106,5 +343,66 @@ ntru_public_key_t *ntru_public_key_create(ntru_param_set_t *params,
|
||||
this->pubkey[i] = pubkey[i];
|
||||
}
|
||||
|
||||
/* generate public key encoding */
|
||||
generate_encoding(this);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ntru_public_key_t *ntru_public_key_create_from_data(ntru_drbg_t *drbg,
|
||||
chunk_t data)
|
||||
{
|
||||
private_ntru_public_key_t *this;
|
||||
size_t header_len, pubkey_packed_len;
|
||||
ntru_param_set_t *params;
|
||||
|
||||
header_len = 2 + NTRU_OID_LEN;
|
||||
|
||||
/* check the NTRU public key header format */
|
||||
if (data.len < header_len ||
|
||||
data.ptr[0] != NTRU_PUBKEY_TAG ||
|
||||
data.ptr[1] != NTRU_OID_LEN)
|
||||
{
|
||||
DBG1(DBG_LIB, "received NTRU public key with invalid header");
|
||||
return NULL;
|
||||
}
|
||||
params = ntru_param_set_get_by_oid(data.ptr + 2);
|
||||
|
||||
if (!params)
|
||||
{
|
||||
DBG1(DBG_LIB, "received NTRU public key with unknown OID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pubkey_packed_len = (params->N * params->q_bits + 7) / 8;
|
||||
|
||||
if (data.len < header_len + pubkey_packed_len)
|
||||
{
|
||||
DBG1(DBG_LIB, "received NTRU public key with wrong packed key size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_id = _get_id,
|
||||
.get_encoding = _get_encoding,
|
||||
.encrypt = _encrypt,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.params = params,
|
||||
.pubkey = malloc(params->N * sizeof(uint16_t)),
|
||||
.encoding = chunk_clone(data),
|
||||
.drbg = drbg->get_ref(drbg),
|
||||
);
|
||||
|
||||
/* unpack the encoded public key */
|
||||
ntru_octets_2_elements(pubkey_packed_len, data.ptr + header_len,
|
||||
params->q_bits, this->pubkey);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_public_key_create_from_data);
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
typedef struct ntru_public_key_t ntru_public_key_t;
|
||||
|
||||
#include "ntru_param_set.h"
|
||||
#include "ntru_drbg.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
@ -32,6 +33,13 @@ typedef struct ntru_public_key_t ntru_public_key_t;
|
||||
*/
|
||||
struct ntru_public_key_t {
|
||||
|
||||
/**
|
||||
* Returns NTRU parameter set ID of the public key
|
||||
*
|
||||
* @return NTRU parameter set ID
|
||||
*/
|
||||
ntru_param_set_id_t (*get_id)(ntru_public_key_t *this);
|
||||
|
||||
/**
|
||||
* Returns the packed encoding of the NTRU encryption public key
|
||||
*
|
||||
@ -39,6 +47,16 @@ struct ntru_public_key_t {
|
||||
*/
|
||||
chunk_t (*get_encoding)(ntru_public_key_t *this);
|
||||
|
||||
/**
|
||||
* Encrypts a plaintext with the NTRU public key
|
||||
*
|
||||
* @param ciphertext Plaintext
|
||||
* @param plaintext Ciphertext
|
||||
* @return TRUE if encryption was successful
|
||||
*/
|
||||
bool (*encrypt)(ntru_public_key_t *this, chunk_t plaintext,
|
||||
chunk_t *ciphertext);
|
||||
|
||||
/**
|
||||
* Destroy ntru_public_key_t object
|
||||
*/
|
||||
@ -46,14 +64,25 @@ struct ntru_public_key_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an NTRU encryption public key
|
||||
* Creates an NTRU encryption public key from coefficients
|
||||
*
|
||||
* @param drbg Deterministic random bit generator
|
||||
* @param params NTRU encryption parameter set to be used
|
||||
* @param pubkey Coefficients of public key polynomial h
|
||||
*/
|
||||
ntru_public_key_t *ntru_public_key_create(ntru_param_set_t *params,
|
||||
ntru_public_key_t *ntru_public_key_create(ntru_drbg_t *drbg,
|
||||
ntru_param_set_t *params,
|
||||
uint16_t *pubkey);
|
||||
|
||||
/**
|
||||
* Creates an NTRU encryption public key from encoding
|
||||
*
|
||||
* @param drbg Deterministic random bit generator
|
||||
* @param data Encoded NTRU public key
|
||||
*/
|
||||
ntru_public_key_t *ntru_public_key_create_from_data(ntru_drbg_t *drbg,
|
||||
chunk_t data);
|
||||
|
||||
|
||||
#endif /** NTRU_PUBLIC_KEY_H_ @}*/
|
||||
|
||||
|
||||
@ -15,8 +15,7 @@
|
||||
|
||||
#include "ntru_trits.h"
|
||||
#include "ntru_mgf1.h"
|
||||
|
||||
#include "ntru_crypto/ntru_crypto_ntru_convert.h"
|
||||
#include "ntru_convert.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <utils/test.h>
|
||||
|
||||
@ -49,6 +49,12 @@ IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_param_set_get_by_id, ntru_param_set_t* ,
|
||||
IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_private_key_create, ntru_private_key_t*,
|
||||
ntru_drbg_t *drbg, ntru_param_set_t *params)
|
||||
|
||||
IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_private_key_create_from_data, ntru_private_key_t*,
|
||||
ntru_drbg_t *drbg, chunk_t data)
|
||||
|
||||
IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_public_key_create_from_data, ntru_public_key_t*,
|
||||
ntru_drbg_t *drbg, chunk_t data)
|
||||
|
||||
/**
|
||||
* NTRU parameter sets to test
|
||||
*/
|
||||
@ -1086,22 +1092,74 @@ START_TEST(test_ntru_privkey)
|
||||
|
||||
privkey = TEST_FUNCTION(ntru, ntru_private_key_create, drbg, params);
|
||||
ck_assert(privkey);
|
||||
ck_assert(privkey->get_id(privkey) == privkey_tests[_i].id);
|
||||
|
||||
privkey_encoding = privkey->get_encoding(privkey);
|
||||
encoding = privkey_tests[_i].encoding;
|
||||
ck_assert(chunk_equals(privkey_encoding, encoding));
|
||||
|
||||
|
||||
pubkey= privkey->get_public_key(privkey);
|
||||
pubkey_encoding = pubkey->get_encoding(pubkey);
|
||||
/* load private key as a packed blob */
|
||||
privkey->destroy(privkey);
|
||||
privkey = ntru_private_key_create_from_data(drbg, chunk_empty);
|
||||
ck_assert(privkey == NULL);
|
||||
|
||||
encoding = chunk_clone(encoding);
|
||||
encoding.ptr[0] = NTRU_PUBKEY_TAG;
|
||||
privkey = ntru_private_key_create_from_data(drbg, encoding);
|
||||
ck_assert(privkey == NULL);
|
||||
|
||||
encoding.ptr[0] = NTRU_PRIVKEY_TRITS_TAG;
|
||||
privkey = ntru_private_key_create_from_data(drbg, encoding);
|
||||
if (params->is_product_form)
|
||||
{
|
||||
ck_assert(privkey == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ck_assert(privkey != NULL);
|
||||
privkey->destroy(privkey);
|
||||
}
|
||||
|
||||
encoding.ptr[0] = NTRU_PRIVKEY_INDICES_TAG;
|
||||
privkey = ntru_private_key_create_from_data(drbg, encoding);
|
||||
if (params->is_product_form)
|
||||
{
|
||||
ck_assert(privkey != NULL);
|
||||
privkey->destroy(privkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
ck_assert(privkey == NULL);
|
||||
}
|
||||
|
||||
encoding.ptr[0] = NTRU_PRIVKEY_DEFAULT_TAG;
|
||||
encoding.ptr[1] = NTRU_OID_LEN - 1;
|
||||
privkey = ntru_private_key_create_from_data(drbg, encoding);
|
||||
ck_assert(privkey == NULL);
|
||||
|
||||
encoding.ptr[1] = NTRU_OID_LEN;
|
||||
encoding.ptr[2] = 0xff;
|
||||
privkey = ntru_private_key_create_from_data(drbg, encoding);
|
||||
ck_assert(privkey == NULL);
|
||||
|
||||
encoding.ptr[2] = params->oid[0];
|
||||
privkey = ntru_private_key_create_from_data(drbg, encoding);
|
||||
privkey_encoding = privkey->get_encoding(privkey);
|
||||
ck_assert(chunk_equals(privkey_encoding, encoding));
|
||||
|
||||
pubkey = privkey->get_public_key(privkey);
|
||||
pubkey_encoding = pubkey->get_encoding(pubkey);
|
||||
|
||||
encoding.ptr[0] = NTRU_PUBKEY_TAG;
|
||||
encoding.len = pubkey_encoding.len;
|
||||
ck_assert(chunk_equals(pubkey_encoding, encoding));
|
||||
|
||||
/* get encoding a second time without generating it again internally */
|
||||
/* load public key as a packed blob */
|
||||
pubkey->destroy(pubkey);
|
||||
pubkey = ntru_public_key_create_from_data(drbg, encoding);
|
||||
pubkey_encoding = pubkey->get_encoding(pubkey);
|
||||
|
||||
ck_assert(chunk_equals(pubkey_encoding, encoding));
|
||||
|
||||
chunk_free(&encoding);
|
||||
privkey->destroy(privkey);
|
||||
pubkey->destroy(pubkey);
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
|
||||
The key exchange is based on NTRU encryption with a security strength of 128 bits.
|
||||
The ANSI X9.98 NTRU encryption parameter set used is optimized for bandwidth.
|
||||
<p/>
|
||||
The authentication is based on <b>X.509 certificates</b>. Upon the successful
|
||||
establishment of the IPsec tunnel, <b>leftfirewall=yes</b> automatically
|
||||
inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||
In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b>
|
||||
pings client <b>bob</b> located behind gateway <b>sun</b>.
|
||||
9
testing/tests/ikev2/net2net-ntru-bandwidth/evaltest.dat
Normal file
9
testing/tests/ikev2/net2net-ntru-bandwidth/evaltest.dat
Normal file
@ -0,0 +1,9 @@
|
||||
moon::ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||
sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||
moon::ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
|
||||
sun:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
|
||||
moon::ipsec statusall 2> /dev/null::net-net.*IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/NTRU_128::YES
|
||||
sun::ipsec statusall 2> /dev/null::net-net.*IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/NTRU_128::YES
|
||||
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
|
||||
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
@ -0,0 +1,25 @@
|
||||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
charondebug="ike 4, lib 4"
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
keyexchange=ikev2
|
||||
ike=aes128-sha256-ntru128!
|
||||
esp=aes128-sha256!
|
||||
mobike=no
|
||||
|
||||
conn net-net
|
||||
left=PH_IP_MOON
|
||||
leftcert=moonCert.pem
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.0/16
|
||||
leftfirewall=yes
|
||||
right=PH_IP_SUN
|
||||
rightid=@sun.strongswan.org
|
||||
rightsubnet=10.2.0.0/16
|
||||
auto=add
|
||||
@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 ntru revocation hmac stroke kernel-netlink socket-default updown
|
||||
|
||||
multiple_authentication = no
|
||||
send_vendor_id = yes
|
||||
|
||||
plugins {
|
||||
ntru {
|
||||
parameter_set = x9_98_bandwidth
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
charondebug="ike 4, lib 4"
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
keyexchange=ikev2
|
||||
ike=aes128-sha256-ntru128!
|
||||
esp=aes128-sha256!
|
||||
mobike=no
|
||||
|
||||
conn net-net
|
||||
left=PH_IP_SUN
|
||||
leftcert=sunCert.pem
|
||||
leftid=@sun.strongswan.org
|
||||
leftsubnet=10.2.0.0/16
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
rightsubnet=10.1.0.0/16
|
||||
auto=add
|
||||
@ -0,0 +1,14 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 ntru revocation hmac stroke kernel-netlink socket-default updown
|
||||
|
||||
multiple_authentication = no
|
||||
send_vendor_id = yes
|
||||
|
||||
plugins {
|
||||
ntru {
|
||||
parameter_set = x9_98_bandwidth
|
||||
}
|
||||
}
|
||||
}
|
||||
5
testing/tests/ikev2/net2net-ntru-bandwidth/posttest.dat
Normal file
5
testing/tests/ikev2/net2net-ntru-bandwidth/posttest.dat
Normal file
@ -0,0 +1,5 @@
|
||||
moon::ipsec stop
|
||||
sun::ipsec stop
|
||||
moon::iptables-restore < /etc/iptables.flush
|
||||
sun::iptables-restore < /etc/iptables.flush
|
||||
|
||||
6
testing/tests/ikev2/net2net-ntru-bandwidth/pretest.dat
Normal file
6
testing/tests/ikev2/net2net-ntru-bandwidth/pretest.dat
Normal file
@ -0,0 +1,6 @@
|
||||
moon::iptables-restore < /etc/iptables.rules
|
||||
sun::iptables-restore < /etc/iptables.rules
|
||||
moon::ipsec start
|
||||
sun::ipsec start
|
||||
moon::sleep 1
|
||||
moon::ipsec up net-net
|
||||
21
testing/tests/ikev2/net2net-ntru-bandwidth/test.conf
Normal file
21
testing/tests/ikev2/net2net-ntru-bandwidth/test.conf
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice moon winnetou sun bob"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-m-w-s-b.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="sun"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon sun"
|
||||
Loading…
x
Reference in New Issue
Block a user