From: Andreas Steffen Date: Sat, 22 Mar 2014 08:50:39 +0000 (+0100) Subject: Completed integration of ntru_crypto library into ntru plugin X-Git-Tag: 5.1.3dr1~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=22e1aa51f94e566dd54e0eae37cc3f045cf59854;p=thirdparty%2Fstrongswan.git Completed integration of ntru_crypto library into ntru plugin --- diff --git a/src/libstrongswan/plugins/ntru/Makefile.am b/src/libstrongswan/plugins/ntru/Makefile.am index fec2a70951..e241554b5b 100644 --- a/src/libstrongswan/plugins/ntru/Makefile.am +++ b/src/libstrongswan/plugins/ntru/Makefile.am @@ -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 diff --git a/src/libstrongswan/plugins/ntru/ntru_convert.c b/src/libstrongswan/plugins/ntru/ntru_convert.c new file mode 100644 index 0000000000..6330b2e39f --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_convert.c @@ -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 . + * + * 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 +#include + +#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; + } +} diff --git a/src/libstrongswan/plugins/ntru/ntru_convert.h b/src/libstrongswan/plugins/ntru/ntru_convert.h new file mode 100644 index 0000000000..31594b1f6c --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_convert.h @@ -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 . + * + * 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 + +/** + * 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_ @}*/ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h deleted file mode 100644 index 33a7e961dd..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h +++ /dev/null @@ -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 - -#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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c deleted file mode 100644 index 3d6dfde41c..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c +++ /dev/null @@ -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 -#include -#include -#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; - } -} - - diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h deleted file mode 100644 index 1c4b35b245..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h +++ /dev/null @@ -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 */ - - diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c deleted file mode 100644 index 01891234fe..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c +++ /dev/null @@ -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 -#include -#include -#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; -} diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c deleted file mode 100644 index 702b574e3a..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c +++ /dev/null @@ -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 -#include -#include -#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; -} diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h deleted file mode 100644 index 637e49c95b..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h +++ /dev/null @@ -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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c deleted file mode 100644 index e5393849c9..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c +++ /dev/null @@ -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 -#include -#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; -} - diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h deleted file mode 100644 index 938e7b2cf0..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h +++ /dev/null @@ -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 - - -/* 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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.c b/src/libstrongswan/plugins/ntru/ntru_drbg.c index 181a589398..ef0d3d9c89 100644 --- a/src/libstrongswan/plugins/ntru/ntru_drbg.c +++ b/src/libstrongswan/plugins/ntru/ntru_drbg.c @@ -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); diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.h b/src/libstrongswan/plugins/ntru/ntru_drbg.h index 38ac718aea..83cef11bee 100644 --- a/src/libstrongswan/plugins/ntru/ntru_drbg.h +++ b/src/libstrongswan/plugins/ntru/ntru_drbg.h @@ -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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_ke.c b/src/libstrongswan/plugins/ntru/ntru_ke.c index 95acffd82b..abaa223362 100644 --- a/src/libstrongswan/plugins/ntru/ntru_ke.c +++ b/src/libstrongswan/plugins/ntru/ntru_ke.c @@ -19,8 +19,6 @@ #include "ntru_private_key.h" #include "ntru_public_key.h" -#include "ntru_crypto/ntru_crypto.h" - #include #include @@ -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); diff --git a/src/libstrongswan/plugins/ntru/ntru_param_set.h b/src/libstrongswan/plugins/ntru/ntru_param_set.h index 20d75dc473..df4e553335 100644 --- a/src/libstrongswan/plugins/ntru/ntru_param_set.h +++ b/src/libstrongswan/plugins/ntru/ntru_param_set.h @@ -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_ @}*/ - diff --git a/src/libstrongswan/plugins/ntru/ntru_private_key.c b/src/libstrongswan/plugins/ntru/ntru_private_key.c index 9e824630d0..fa87fe9c31 100644 --- a/src/libstrongswan/plugins/ntru/ntru_private_key.c +++ b/src/libstrongswan/plugins/ntru/ntru_private_key.c @@ -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 #include @@ -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); + + 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 (wt[0] >= min_wt) && (wt[1] >= min_wt) && (wt[2] >= min_wt); + 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); diff --git a/src/libstrongswan/plugins/ntru/ntru_private_key.h b/src/libstrongswan/plugins/ntru/ntru_private_key.h index ded4be4e31..c6f08440f1 100644 --- a/src/libstrongswan/plugins/ntru/ntru_private_key.h +++ b/src/libstrongswan/plugins/ntru/ntru_private_key.h @@ -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_ @}*/ diff --git a/src/libstrongswan/plugins/ntru/ntru_public_key.c b/src/libstrongswan/plugins/ntru/ntru_public_key.c index 6974b76306..8cfd32f811 100644 --- a/src/libstrongswan/plugins/ntru/ntru_public_key.c +++ b/src/libstrongswan/plugins/ntru/ntru_public_key.c @@ -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 +#include 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); diff --git a/src/libstrongswan/plugins/ntru/ntru_public_key.h b/src/libstrongswan/plugins/ntru/ntru_public_key.h index 2fd5f6484f..baa8eabcd0 100644 --- a/src/libstrongswan/plugins/ntru/ntru_public_key.h +++ b/src/libstrongswan/plugins/ntru/ntru_public_key.h @@ -24,6 +24,7 @@ typedef struct ntru_public_key_t ntru_public_key_t; #include "ntru_param_set.h" +#include "ntru_drbg.h" #include @@ -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_ @}*/ diff --git a/src/libstrongswan/plugins/ntru/ntru_trits.c b/src/libstrongswan/plugins/ntru/ntru_trits.c index f825016299..1abb7671c7 100644 --- a/src/libstrongswan/plugins/ntru/ntru_trits.c +++ b/src/libstrongswan/plugins/ntru/ntru_trits.c @@ -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 #include diff --git a/src/libstrongswan/tests/suites/test_ntru.c b/src/libstrongswan/tests/suites/test_ntru.c index 9e6c5d74da..990c29865b 100644 --- a/src/libstrongswan/tests/suites/test_ntru.c +++ b/src/libstrongswan/tests/suites/test_ntru.c @@ -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)); + /* 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); - pubkey= privkey->get_public_key(privkey); + 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 = chunk_clone(encoding); + 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); diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/description.txt b/testing/tests/ikev2/net2net-ntru-bandwidth/description.txt new file mode 100644 index 0000000000..aab0c68c44 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/description.txt @@ -0,0 +1,9 @@ +A connection between the subnets behind the gateways moon and sun 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. +

+The authentication is based on X.509 certificates. Upon the successful +establishment of the IPsec tunnel, leftfirewall=yes automatically +inserts iptables-based firewall rules that let pass the tunneled traffic. +In order to test both tunnel and firewall, client alice behind gateway moon +pings client bob located behind gateway sun. diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/evaltest.dat b/testing/tests/ikev2/net2net-ntru-bandwidth/evaltest.dat new file mode 100644 index 0000000000..69b5ef754f --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/evaltest.dat @@ -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 diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/ipsec.conf new file mode 100644 index 0000000000..01d114dd91 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/ipsec.conf @@ -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 diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/strongswan.conf new file mode 100644 index 0000000000..17f6111fd9 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/strongswan.conf @@ -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 + } + } +} diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/ipsec.conf new file mode 100644 index 0000000000..e57bec9656 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/ipsec.conf @@ -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 diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/strongswan.conf new file mode 100644 index 0000000000..0d18555046 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/strongswan.conf @@ -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 + } + } +} diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/posttest.dat b/testing/tests/ikev2/net2net-ntru-bandwidth/posttest.dat new file mode 100644 index 0000000000..837738fc6a --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/posttest.dat @@ -0,0 +1,5 @@ +moon::ipsec stop +sun::ipsec stop +moon::iptables-restore < /etc/iptables.flush +sun::iptables-restore < /etc/iptables.flush + diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/pretest.dat b/testing/tests/ikev2/net2net-ntru-bandwidth/pretest.dat new file mode 100644 index 0000000000..c724e5df85 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/pretest.dat @@ -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 diff --git a/testing/tests/ikev2/net2net-ntru-bandwidth/test.conf b/testing/tests/ikev2/net2net-ntru-bandwidth/test.conf new file mode 100644 index 0000000000..646b8b3e64 --- /dev/null +++ b/testing/tests/ikev2/net2net-ntru-bandwidth/test.conf @@ -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"