ARG_ENABL_SET([ctr], [enables the Counter Mode wrapper crypto plugin.])
ARG_ENABL_SET([ccm], [enables the CCM AEAD wrapper crypto plugin.])
ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.])
+ARG_ENABL_SET([ntru], [enables the NTRU crypto plugin.])
ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.])
ARG_ENABL_SET([unity], [enables Cisco Unity extension plugin.])
ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.])
ADD_PLUGIN([ctr], [s charon scripts nm cmd])
ADD_PLUGIN([ccm], [s charon scripts nm cmd])
ADD_PLUGIN([gcm], [s charon scripts nm cmd])
+ADD_PLUGIN([ntru], [s charon scripts nm cmd])
ADD_PLUGIN([attr], [h charon])
ADD_PLUGIN([attr-sql], [h charon])
ADD_PLUGIN([load-tester], [c charon])
AM_CONDITIONAL(USE_CCM, test x$ccm = xtrue)
AM_CONDITIONAL(USE_GCM, test x$gcm = xtrue)
AM_CONDITIONAL(USE_AF_ALG, test x$af_alg = xtrue)
+AM_CONDITIONAL(USE_NTRU, test x$ntru = xtrue)
# charon plugins
# ----------------
src/libstrongswan/plugins/ccm/Makefile
src/libstrongswan/plugins/gcm/Makefile
src/libstrongswan/plugins/af_alg/Makefile
+ src/libstrongswan/plugins/ntru/Makefile
src/libstrongswan/plugins/test_vectors/Makefile
src/libstrongswan/tests/Makefile
src/libhydra/Makefile
endif
endif
+if USE_NTRU
+ SUBDIRS += plugins/ntru
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/ntru/libstrongswan-ntru.la
+endif
+endif
+
if USE_TEST_VECTORS
SUBDIRS += plugins/test_vectors
if MONOLITHIC
0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA
0x05 "sha-1WithRSAEncryption" OID_SHA1_WITH_RSA
0x07 "id-RSAES-OAEP" OID_RSAES_OAEP
+ 0x08 "id-mgf1"
0x09 "id-pSpecified"
0x0B "sha256WithRSAEncryption" OID_SHA256_WITH_RSA
0x0C "sha384WithRSAEncryption" OID_SHA384_WITH_RSA
0x02 ""
0x02 ""
0x4B "TCGID" OID_TCGID
+ 0xc1 ""
+ 0x16 "ntruCryptosystems"
+ 0x01 "eess"
+ 0x01 "eess1"
+ 0x01 "eess1-algs"
+ 0x01 "ntru-EESS1v1-SVES"
+ 0x02 "ntru-EESS1v1-SVSSA"
+ 0x03 "ntru-EESS1v1-NTRUSign"
+ 0x02 "eess1-params"
+ 0x01 "ees251ep1"
+ 0x02 "ees347ep1"
+ 0x03 "ees503ep1"
+ 0x07 "ees251sp2"
+ 0x0C "ees251ep4"
+ 0x0D "ees251ep5"
+ 0x0E "ees251sp3"
+ 0x0F "ees251sp4"
+ 0x10 "ees251sp5"
+ 0x11 "ees251sp6"
+ 0x12 "ees251sp7"
+ 0x13 "ees251sp8"
+ 0x14 "ees251sp9"
+ 0x03 "eess1-encodingMethods"
0x05 "security"
0x05 "mechanisms"
0x07 "id-pkix"
ENUM_NEXT(diffie_hellman_group_names, MODP_NULL, MODP_CUSTOM, ECP_512_BP,
"MODP_NULL",
"MODP_CUSTOM");
-ENUM_END(diffie_hellman_group_names, MODP_CUSTOM);
+ENUM_NEXT(diffie_hellman_group_names, NTRU_112_BIT, NTRU_256_BIT, MODP_CUSTOM,
+ "NTRU_112",
+ "NTRU_128",
+ "NTRU_192",
+ "NTRU_256");
+ENUM_END(diffie_hellman_group_names, NTRU_256_BIT);
/**
MODP_NULL = 1024,
/** MODP group with custom generator/prime */
MODP_CUSTOM = 1025,
+ /** Parameters defined by IEEE 1363.1, in PRIVATE USE */
+ NTRU_112_BIT = 1030,
+ NTRU_128_BIT = 1031,
+ NTRU_192_BIT = 1032,
+ NTRU_256_BIT = 1033
};
/**
%{
/*
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+ * Copyright (C) 2009-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil, Switzerland
*
* 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
ecp256bp, DIFFIE_HELLMAN_GROUP, ECP_256_BP, 0
ecp384bp, DIFFIE_HELLMAN_GROUP, ECP_384_BP, 0
ecp512bp, DIFFIE_HELLMAN_GROUP, ECP_512_BP, 0
+ntru112, DIFFIE_HELLMAN_GROUP, NTRU_112_BIT, 0
+ntru128, DIFFIE_HELLMAN_GROUP, NTRU_128_BIT, 0
+ntru192, DIFFIE_HELLMAN_GROUP, NTRU_192_BIT, 0
+ntru256, DIFFIE_HELLMAN_GROUP, NTRU_256_BIT, 0
noesn, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0
esn, EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+ -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ntru.la
+else
+plugin_LTLIBRARIES = libstrongswan-ntru.la
+endif
+
+libstrongswan_ntru_la_SOURCES = \
+ ntru_plugin.h ntru_plugin.c \
+ ntru_ke.h ntru_ke.c \
+ ntru_crypto/ntru_crypto.h ntru_crypto/ntru_crypto_error.h \
+ ntru_crypto/ntru_crypto_drbg.h ntru_crypto/ntru_crypto_drbg.c \
+ ntru_crypto/ntru_crypto_hash_basics.h \
+ ntru_crypto/ntru_crypto_hash.h ntru_crypto/ntru_crypto_hash.c \
+ ntru_crypto/ntru_crypto_hmac.h ntru_crypto/ntru_crypto_hmac.c \
+ ntru_crypto/ntru_crypto_msbyte_uint32.h \
+ ntru_crypto/ntru_crypto_msbyte_uint32.c \
+ 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_encrypt_param_sets.h \
+ ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c \
+ ntru_crypto/ntru_crypto_ntru_mgf1.h ntru_crypto/ntru_crypto_ntru_mgf1.c \
+ ntru_crypto/ntru_crypto_ntru_poly.h ntru_crypto/ntru_crypto_ntru_poly.c \
+ ntru_crypto/ntru_crypto_platform.h ntru_crypto/ntru_crypto_sha.h\
+ ntru_crypto/ntru_crypto_sha1.h ntru_crypto/ntru_crypto_sha1.c\
+ ntru_crypto/ntru_crypto_sha2.h ntru_crypto/ntru_crypto_sha2.c\
+ ntru_crypto/ntru_crypto_sha256.h ntru_crypto/ntru_crypto_sha256.c
+
+libstrongswan_ntru_la_LDFLAGS = -module -avoid-version
+
+
--- /dev/null
+/******************************************************************************
+ * 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 "ntru_crypto_platform.h"
+#include "ntru_crypto_drbg.h"
+#include "ntru_crypto_error.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 */
+
+#if defined ( __cplusplus )
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* parameter set ID list */
+
+typedef enum _NTRU_ENCRYPT_PARAM_SET_ID {
+ NTRU_EES401EP1,
+ NTRU_EES449EP1,
+ NTRU_EES677EP1,
+ NTRU_EES1087EP2,
+ NTRU_EES541EP1,
+ NTRU_EES613EP1,
+ NTRU_EES887EP1,
+ NTRU_EES1171EP1,
+ NTRU_EES659EP1,
+ NTRU_EES761EP1,
+ NTRU_EES1087EP1,
+ NTRU_EES1499EP1,
+ NTRU_EES401EP2,
+ NTRU_EES439EP1,
+ NTRU_EES593EP1,
+ NTRU_EES743EP1,
+} NTRU_ENCRYPT_PARAM_SET_ID;
+
+
+/* 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_RESULT(r) ((uint32_t)((r) ? NTRU_ERROR_BASE + (r) : (r)))
+#define NTRU_RET(r) return NTRU_RESULT((r))
+
+
+/* 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 DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than ct) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ * (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
+ * maximum plaintext length for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ * invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
+ * is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ * allocated from the heap.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt(
+ DRBG_HANDLE drbg_handle, /* 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 */
+
+
+/* ntru_crypto_ntru_decrypt
+ *
+ * Implements NTRU decryption (SVES) for the parameter set specified in
+ * the private key blob.
+ *
+ * The maximum size of the output plaintext may be queried by invoking
+ * this function with pt = NULL. In this case, no decryption is performed,
+ * NTRU_OK is returned, and the maximum size the plaintext could be is
+ * returned in pt_len.
+ * Note that until the decryption is performed successfully, the actual size
+ * of the resulting plaintext cannot be known.
+ *
+ * When pt != NULL, at invocation *pt_len must be the size of the pt buffer.
+ * Upon return it is the actual size of the plaintext.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than pt) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ * (privkey_blob) is zero, or if ct_len is invalid for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
+ * invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
+ * is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ * allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_decrypt(
+ uint16_t privkey_blob_len, /* in - no. of octets in private key
+ blob */
+ uint8_t const *privkey_blob, /* in - pointer to private key */
+ uint16_t ct_len, /* in - no. of octets in ciphertext */
+ uint8_t const *ct, /* in - pointer to ciphertext */
+ uint16_t *pt_len, /* in/out - no. of octets in pt, addr for
+ no. of octets in plaintext */
+ uint8_t *pt); /* out - address for plaintext */
+
+
+/* ntru_crypto_ntru_encrypt_keygen
+ *
+ * Implements key generation for NTRUEncrypt for the parameter set specified.
+ *
+ * Before invoking this function, a DRBG must be instantiated using
+ * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
+ * instantiation the requested security strength must be at least as large
+ * as the security strength of the NTRU parameter set being used.
+ * Failure to instantiate the DRBG with the proper security strength will
+ * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * The required minimum size of the output private-key buffer (privkey_blob)
+ * may be queried by invoking this function with privkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for privkey_blob is returned in privkey_blob_len.
+ *
+ * The required minimum sizes of both pubkey_blob and privkey_blob may be
+ * queried as described above, in a single invocation of this function.
+ *
+ * When pubkey_blob != NULL and privkey_blob != NULL, at invocation
+ * *pubkey_blob_len must be the size of the pubkey_blob buffer and
+ * *privkey_blob_len must be the size of the privkey_blob buffer.
+ * Upon return, *pubkey_blob_len is the actual size of the public-key blob
+ * and *privkey_blob_len is the actual size of the private-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than pubkey_blob or privkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
+ * ID is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
+ * buffer or the privkey_blob buffer is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ * allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
+ * not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
+ * Should this occur, this function should simply be invoked again.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt_keygen(
+ DRBG_HANDLE drbg_handle, /* in - handle of DRBG */
+ NTRU_ENCRYPT_PARAM_SET_ID param_set_id, /* in - parameter set ID */
+ uint16_t *pubkey_blob_len, /* in/out - no. of octets in
+ pubkey_blob, addr
+ for no. of octets
+ in pubkey_blob */
+ uint8_t *pubkey_blob, /* out - address for
+ public key blob */
+ uint16_t *privkey_blob_len, /* in/out - no. of octets in
+ privkey_blob, addr
+ for no. of octets
+ in privkey_blob */
+ uint8_t *privkey_blob); /* out - address for
+ private key blob */
+
+
+/* ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo
+ *
+ * DER-encodes an NTRUEncrypt public-key from a public-key blob into a
+ * SubjectPublicKeyInfo field for inclusion in an X.509 certificate.
+ *
+ * The required minimum size of the output SubjectPublicKeyInfo buffer
+ * (encoded_subjectPublicKeyInfo) may be queried by invoking this function
+ * with encoded_subjectPublicKeyInfo = NULL. In this case, no encoding is
+ * performed, NTRU_OK is returned, and the required minimum size for
+ * encoded_subjectPublicKeyInfo is returned in encoded_subjectPublicKeyInfo_len.
+ *
+ * When encoded_subjectPublicKeyInfo != NULL, at invocation
+ * *encoded_subjectPublicKeyInfo_len must be the size of the
+ * encoded_subjectPublicKeyInfo buffer.
+ * Upon return, it is the actual size of the encoded public key.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than encoded_subjectPublicKeyInfo) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if pubkey_blob_len is zero.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ * invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the SubjectPublicKeyInfo
+ * buffer is too small.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+ uint16_t pubkey_blob_len, /* in - no. of octets in public-key
+ blob */
+ uint8_t const *pubkey_blob, /* in - ptr to public-key blob */
+ uint16_t *encoded_subjectPublicKeyInfo_len,
+ /* in/out - no. of octets in encoded info,
+ address for no. of octets in
+ encoded info */
+ uint8_t *encoded_subjectPublicKeyInfo);
+ /* out - address for encoded info */
+
+
+/* ntru_crypto_ntru_encrypt_SubjectPublicKeyInfo2PublicKey
+ *
+ * Decodes a DER-encoded NTRUEncrypt public-key from a
+ * SubjectPublicKeyInfo field in an X.509 certificate and returns the
+ * public-key blob itself.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no decoding is performed, NTRU_OK is returned, and the
+ * required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * When pubkey_blob != NULL, at invocation *pubkey_blob_len must be the
+ * size of the pubkey_blob buffer.
+ * Upon return, it is the actual size of the public-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than pubkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_ENCODING if the encoded data is
+ * an invalid encoding of an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_OID_NOT_RECOGNIZED if the
+ * encoded data contains an OID that identifies an object other than
+ * an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the pubkey_blob buffer
+ * is too small.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(
+ uint8_t const *encoded_data, /* in - ptr to subjectPublicKeyInfo
+ in the encoded data */
+ uint16_t *pubkey_blob_len, /* in/out - no. of octets in pubkey blob,
+ address for no. of octets in
+ pubkey blob */
+ uint8_t *pubkey_blob, /* out - address for pubkey blob */
+ uint8_t **next); /* out - address for ptr to encoded
+ data following the
+ subjectPublicKeyInfo */
+
+
+#if defined ( __cplusplus )
+}
+#endif /* __cplusplus */
+
+
+#endif /* NTRU_CRYPTO_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_drbg.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_drbg.c
+ *
+ * Contents: Implementation of a SHA-256 HMAC-based deterministic random byte
+ * generator (HMAC_DRBG) as defined in ANSI X9.82, Part 3 - 2007.
+ *
+ * This implementation:
+ * - allows for MAX_INSTANTIATIONS simultaneous drbg instantiations
+ * (may be overridden on compiler command line)
+ * - has a maximum security strength of 256 bits
+ * - automatically uses SHA-256 for all security strengths
+ * - allows a personalization string of up to MAX_PERS_STR_BYTES bytes
+ * - implments reseeding
+ * - does not implement additional input for reseeding or generation
+ * - does not implement predictive resistance
+ * - limits the number of bytes requested in one invocation of generate to
+ * MAX_BYTES_PER_REQUEST
+ * - uses a callback function to allow the caller to supply the
+ * Get_entropy_input routine (entropy function)
+ * - limits the number of bytes returned from the entropy function to
+ * MAX_ENTROPY_NONCE_BYTES
+ * - gets the nonce bytes along with the entropy input from the entropy
+ * function
+ * - automatically reseeds an instantitation after MAX_REQUESTS calls to
+ * generate
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ntru_crypto_drbg.h"
+#include "ntru_crypto_hmac.h"
+
+
+/************************
+ * HMAC_DRBG parameters *
+ ************************/
+
+/* Note: nonce size is sec_strength_bits/2 */
+#define HMAC_DRBG_MAX_MIN_ENTROPY_NONCE_BYTES \
+ (DRBG_MAX_SEC_STRENGTH_BITS + DRBG_MAX_SEC_STRENGTH_BITS/2)/8
+#define HMAC_DRBG_MAX_ENTROPY_NONCE_BYTES \
+ HMAC_DRBG_MAX_MIN_ENTROPY_NONCE_BYTES * DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY
+#define HMAC_DRBG_MAX_REQUESTS 0xffffffff
+
+
+/*******************
+ * DRBG structures *
+ *******************/
+
+/* SHA256_HMAC_DRBG state structure */
+
+typedef struct {
+ uint32_t sec_strength; /* security strength in bits */
+ uint32_t requests_left; /* generation requests remaining
+ before reseeding */
+ ENTROPY_FN entropy_fn; /* pointer to entropy function */
+ NTRU_CRYPTO_HMAC_CTX *hmac_ctx; /* pointer to HMAC context */
+ uint8_t V[33]; /* md_len size internal state + 1 */
+} SHA256_HMAC_DRBG_STATE;
+
+
+/* DRBG state structure
+ * Note: this could contain a DRBG_TYPE to direct allocation, instantiation,
+ * and generation to multiple types of DRBGs; at present only the
+ * SHA256_HMAC_DRBG is implemented
+ */
+
+typedef struct {
+ uint32_t handle;
+ void *state;
+} DRBG_STATE;
+
+
+/*************
+ * DRBG DATA *
+ *************/
+
+/* array of drbg states */
+
+static DRBG_STATE drbg_state[DRBG_MAX_INSTANTIATIONS];
+
+
+/******************************
+ * SHA256 HMAC_DRBG functions *
+ ******************************/
+
+/* sha256_hmac_drbg_update
+ *
+ * This routine is the SHA-256 HMAC_DRBG derivation function for
+ * instantiation, and reseeding, and it is used in generation as well.
+ * It updates the internal state.
+ *
+ * For instantiation, provided_data1 holds the entropy input and nonce;
+ * provided_data2 holds the optional personalization string. Combined, this
+ * is the seed material.
+ *
+ * For reseeding, provided_data1 holds the entropy input;
+ * provided_data2 is NULL (because this implementation does not support
+ * additional input).
+ *
+ * For byte generation, both provided_data1 and provided_data2 are NULL.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns HMAC errors if they occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_update(
+ SHA256_HMAC_DRBG_STATE *s,
+ uint8_t *key, /* md_len size array */
+ uint32_t md_len,
+ uint8_t const *provided_data1,
+ uint32_t provided_data1_bytes,
+ uint8_t const *provided_data2,
+ uint32_t provided_data2_bytes)
+{
+ uint32_t result;
+
+ /* new key = HMAC(K, V || 0x00 [|| provided data1 [|| provided data2]] */
+
+ if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) != NTRU_CRYPTO_HMAC_OK)
+ return result;
+ s->V[md_len] = 0x00;
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len + 1)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if (provided_data1) {
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data1,
+ provided_data1_bytes)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if (provided_data2) {
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data2,
+ provided_data2_bytes)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ }
+ }
+ if ((result = ntru_crypto_hmac_final(s->hmac_ctx, key)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_set_key(s->hmac_ctx, key)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+
+ /* new V = HMAC(K, V) */
+
+ if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) != NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_final(s->hmac_ctx, s->V)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+
+ /* if provided data exists, update K and V again */
+
+ if (provided_data1) {
+
+ /* new key = HMAC(K, V || 0x01 || provided data1 [|| provided data2] */
+
+ if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ s->V[md_len] = 0x01;
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len + 1)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data1,
+ provided_data1_bytes)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if (provided_data2) {
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data2,
+ provided_data2_bytes)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ }
+ if ((result = ntru_crypto_hmac_final(s->hmac_ctx, key)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_set_key(s->hmac_ctx, key)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+
+ /* new V = HMAC(K, V) */
+
+ if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_final(s->hmac_ctx, s->V)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ }
+
+ memset(key, 0, md_len);
+ DRBG_RET(DRBG_OK);
+}
+
+
+/* sha256_hmac_drbg_instantiate
+ *
+ * This routine allocates and initializes a SHA-256 HMAC_DRBG internal state.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_BAD_LENGTH if the personalization string is too long.
+ * Returns DRBG_OUT_OF_MEMORY if the internal state cannot be allocated.
+ * Returns errors from HASH or SHA256 if those errors occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_instantiate(
+ uint32_t sec_strength_bits, /* strength to instantiate */
+ uint8_t const *pers_str,
+ uint32_t pers_str_bytes,
+ ENTROPY_FN entropy_fn,
+ SHA256_HMAC_DRBG_STATE **state)
+{
+ uint8_t entropy_nonce[HMAC_DRBG_MAX_ENTROPY_NONCE_BYTES];
+ uint32_t entropy_nonce_bytes;
+ uint32_t min_bytes_of_entropy;
+ uint8_t num_bytes_per_byte_of_entropy;
+ uint8_t key[32]; /* array of md_len size */
+ SHA256_HMAC_DRBG_STATE *s;
+ uint32_t result;
+ uint32_t i;
+
+ /* check arguments */
+
+ if (pers_str_bytes > HMAC_DRBG_MAX_PERS_STR_BYTES)
+ DRBG_RET(DRBG_BAD_LENGTH);
+
+ /* calculate number of bytes needed for the entropy input and nonce
+ * for a SHA256_HMAC_DRBG, and get them from the entropy source
+ */
+
+ if (entropy_fn(GET_NUM_BYTES_PER_BYTE_OF_ENTROPY,
+ &num_bytes_per_byte_of_entropy) == 0)
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+ if ((num_bytes_per_byte_of_entropy == 0) ||
+ (num_bytes_per_byte_of_entropy >
+ DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY))
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+
+ min_bytes_of_entropy = (sec_strength_bits + sec_strength_bits/2) / 8;
+ entropy_nonce_bytes = min_bytes_of_entropy * num_bytes_per_byte_of_entropy;
+ for (i = 0; i < entropy_nonce_bytes; i++)
+ if (entropy_fn(GET_BYTE_OF_ENTROPY, entropy_nonce+i) == 0)
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+
+ /* allocate SHA256_HMAC_DRBG state */
+
+ s = (SHA256_HMAC_DRBG_STATE*) malloc(sizeof(SHA256_HMAC_DRBG_STATE));
+ if (s == NULL) {
+ DRBG_RET(DRBG_OUT_OF_MEMORY);
+ }
+
+ /* allocate HMAC context */
+
+ memset(key, 0, sizeof(key));
+ if ((result = ntru_crypto_hmac_create_ctx(NTRU_CRYPTO_HASH_ALGID_SHA256,
+ key, sizeof(key),
+ &s->hmac_ctx)) !=
+ NTRU_CRYPTO_HMAC_OK) {
+ free(s);
+ return result;
+ }
+
+ /* init and update internal state */
+
+ memset(s->V, 0x01, sizeof(s->V));
+ if ((result = sha256_hmac_drbg_update(s, key, sizeof(key),
+ entropy_nonce, entropy_nonce_bytes,
+ pers_str, pers_str_bytes)) != DRBG_OK) {
+ (void) ntru_crypto_hmac_destroy_ctx(s->hmac_ctx);
+ memset(s->V, 0, sizeof(s->V));
+ free(s);
+ }
+ memset(entropy_nonce, 0, sizeof(entropy_nonce));
+
+ /* init instantiation parameters */
+
+ s->sec_strength = sec_strength_bits;
+ s->requests_left = HMAC_DRBG_MAX_REQUESTS;
+ s->entropy_fn = entropy_fn;
+ *state = s;
+
+ return result;
+}
+
+
+/* sha256_hmac_drbg_free
+ *
+ * This routine frees a SHA-256 HMAC_DRBG internal state.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ */
+
+static void
+sha256_hmac_drbg_free(
+ SHA256_HMAC_DRBG_STATE *s)
+{
+ if (s->hmac_ctx) {
+ (void) ntru_crypto_hmac_destroy_ctx(s->hmac_ctx);
+ }
+ memset(s->V, 0, sizeof(s->V));
+ s->sec_strength = 0;
+ s->requests_left = 0;
+ s->entropy_fn = NULL;
+ free(s);
+}
+
+
+/* sha256_hmac_drbg_reseed
+ *
+ * This function reseeds an instantiated SHA256_HMAC DRBG.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns HMAC errors if they occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_reseed(
+ SHA256_HMAC_DRBG_STATE *s)
+{
+ uint8_t entropy[HMAC_DRBG_MAX_ENTROPY_NONCE_BYTES];
+ uint32_t entropy_bytes;
+ uint32_t min_bytes_of_entropy;
+ uint8_t num_bytes_per_byte_of_entropy;
+ uint8_t key[32]; // array of md_len size for sha256_hmac_drbg_update()
+ uint32_t result;
+ uint32_t i;
+
+ /* calculate number of bytes needed for the entropy input
+ * for a SHA256_HMAC_DRBG, and get them from the entropy source
+ */
+
+ if (s->entropy_fn(GET_NUM_BYTES_PER_BYTE_OF_ENTROPY,
+ &num_bytes_per_byte_of_entropy) == 0)
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+ if ((num_bytes_per_byte_of_entropy == 0) ||
+ (num_bytes_per_byte_of_entropy >
+ DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY))
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+
+ min_bytes_of_entropy = s->sec_strength / 8;
+ entropy_bytes = min_bytes_of_entropy * num_bytes_per_byte_of_entropy;
+ for (i = 0; i < entropy_bytes; i++)
+ if (s->entropy_fn(GET_BYTE_OF_ENTROPY, entropy+i) == 0)
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+
+ /* update internal state */
+
+ if ((result = sha256_hmac_drbg_update(s, key, sizeof(key),
+ entropy, entropy_bytes, NULL, 0)) !=
+ DRBG_OK)
+ return result;
+
+ /* reset request counter */
+
+ s->requests_left = HMAC_DRBG_MAX_REQUESTS;
+ DRBG_RET(DRBG_OK);
+}
+
+
+/* sha256_hmac_drbg_generate
+ *
+ * This routine generates pseudorandom bytes from a SHA256_HMAC DRBG.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_BAD_LENGTH if too many bytes are requested or the requested
+ * security strength is too large.
+ * Returns HMAC errors if they occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_generate(
+ SHA256_HMAC_DRBG_STATE *s,
+ uint32_t sec_strength_bits,
+ uint32_t num_bytes,
+ uint8_t *out)
+{
+ uint8_t key[32]; // array of md_len size for sha256_hmac_drbg_update()
+ uint32_t result;
+
+ /* check if number of bytes requested exceeds the maximum allowed */
+
+ if (num_bytes > HMAC_DRBG_MAX_BYTES_PER_REQUEST)
+ DRBG_RET(DRBG_BAD_LENGTH);
+
+ /* check if drbg has adequate security strength */
+
+ if (sec_strength_bits > s->sec_strength)
+ DRBG_RET(DRBG_BAD_LENGTH);
+
+ /* check if max requests have been exceeded */
+
+ if (s->requests_left == 0)
+ if ((result = sha256_hmac_drbg_reseed(s)) != DRBG_OK)
+ return result;
+
+ /* generate pseudorandom bytes */
+
+ while (num_bytes > 0) {
+
+ /* generate md_len bytes = V = HMAC(K, V) */
+
+ if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V,
+ sizeof(key))) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+ if ((result = ntru_crypto_hmac_final(s->hmac_ctx, s->V)) !=
+ NTRU_CRYPTO_HMAC_OK)
+ return result;
+
+ /* copy generated bytes to output buffer */
+
+ if (num_bytes < sizeof(key)) {
+ memcpy(out, s->V, num_bytes);
+ num_bytes = 0;
+ } else {
+ memcpy(out, s->V, sizeof(key));
+ out += sizeof(key);
+ num_bytes -= sizeof(key);
+ }
+ }
+
+ /* update internal state */
+
+ if ((result = sha256_hmac_drbg_update(s, key, sizeof(key),
+ NULL, 0, NULL, 0)) != DRBG_OK)
+ return result;
+ s->requests_left--;
+
+ DRBG_RET(DRBG_OK);
+}
+
+
+/******************
+ * DRBG functions *
+ ******************/
+
+/* drbg_get_new_drbg
+ *
+ * This routine finds an uninstantiated drbg state and returns a pointer to it.
+ *
+ * Returns a pointer to an uninstantiated drbg state if found.
+ * Returns NULL if all drbg states are instantiated.
+ */
+
+static DRBG_STATE *
+drbg_get_new_drbg()
+{
+ int i;
+
+ for (i = 0; i < DRBG_MAX_INSTANTIATIONS; i++) {
+ if (drbg_state[i].state == NULL)
+ return drbg_state+i;
+ }
+ return NULL;
+}
+
+
+/* drbg_get_drbg
+ *
+ * This routine finds an instantiated drbg state given its handle, and returns
+ * a pointer to it.
+ *
+ * Returns a pointer to the drbg state if found.
+ * Returns NULL if the drbg state is not found.
+ */
+
+static DRBG_STATE *
+drbg_get_drbg(
+ DRBG_HANDLE handle) /* in/out - drbg handle */
+{
+ int i;
+
+ for (i = 0; i < DRBG_MAX_INSTANTIATIONS; i++) {
+ if ((drbg_state[i].handle == handle) && drbg_state[i].state)
+ return drbg_state+i;
+ }
+ return NULL;
+}
+
+
+/* drbg_get_new_handle
+ *
+ * This routine gets a new, unique 32-bit handle.
+ *
+ * Returns the new DRBG handle.
+ */
+
+static DRBG_HANDLE
+drbg_get_new_handle(void)
+{
+ DRBG_HANDLE h = 0;
+
+ /* ensure the new handle is unique:
+ * if it already exists, increment it
+ */
+
+ while (drbg_get_drbg(h) != NULL)
+ ++h;
+
+ return h;
+}
+
+
+/********************
+ * Public functions *
+ ********************/
+
+/* ntru_crypto_drbg_instantiate
+ *
+ * This routine instantiates a drbg with the requested security strength.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ * or the personalization string is too large.
+ * Returns DRBG_ERROR_BASE + DRBG_OUT_OF_MEMORY if the internal state cannot be
+ * allocated from the heap.
+ */
+
+uint32_t
+ntru_crypto_drbg_instantiate(
+ uint32_t sec_strength_bits, /* in - requested sec strength in bits */
+ uint8_t const *pers_str, /* in - ptr to personalization string */
+ uint32_t pers_str_bytes, /* in - no. personalization str bytes */
+ ENTROPY_FN entropy_fn, /* in - pointer to entropy function */
+ DRBG_HANDLE *handle) /* out - address for drbg handle */
+{
+ DRBG_STATE *drbg = NULL;
+ SHA256_HMAC_DRBG_STATE *state = NULL;
+ uint32_t result;
+
+ /* check arguments */
+
+ if ((!pers_str && pers_str_bytes) || !entropy_fn || !handle)
+ DRBG_RET(DRBG_BAD_PARAMETER);
+ if (sec_strength_bits > DRBG_MAX_SEC_STRENGTH_BITS)
+ DRBG_RET(DRBG_BAD_LENGTH);
+ if (pers_str && (pers_str_bytes == 0))
+ pers_str = NULL;
+
+ /* set security strength */
+
+ if (sec_strength_bits <= 112) {
+ sec_strength_bits = 112;
+ } else if (sec_strength_bits <= 128) {
+ sec_strength_bits = 128;
+ } else if (sec_strength_bits <= 192) {
+ sec_strength_bits = 192;
+ } else {
+ sec_strength_bits = 256;
+ }
+
+ /* get an uninstantiated drbg */
+
+ if ((drbg = drbg_get_new_drbg()) == NULL)
+ DRBG_RET(DRBG_NOT_AVAILABLE);
+
+ /* init entropy function */
+
+ if (entropy_fn(INIT, NULL) == 0)
+ DRBG_RET(DRBG_ENTROPY_FAIL);
+
+ /* instantiate a SHA-256 HMAC_DRBG */
+
+ if ((result = sha256_hmac_drbg_instantiate(sec_strength_bits,
+ pers_str, pers_str_bytes,
+ entropy_fn,
+ &state)) != DRBG_OK)
+ return result;
+
+ /* init drbg state */
+
+ drbg->handle = drbg_get_new_handle();
+ drbg->state = state;
+
+ /* return drbg handle */
+
+ *handle = drbg->handle;
+ DRBG_RET(DRBG_OK);
+}
+
+
+/* ntru_crypto_drbg_uninstantiate
+ *
+ * This routine frees a drbg given its handle.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ */
+
+uint32_t
+ntru_crypto_drbg_uninstantiate(
+ DRBG_HANDLE handle) /* in - drbg handle */
+{
+ DRBG_STATE *drbg = NULL;
+
+ /* find the instantiated drbg */
+
+ if ((drbg = drbg_get_drbg(handle)) == NULL)
+ DRBG_RET(DRBG_BAD_PARAMETER);
+
+ /* zero and free drbg state */
+
+ if (drbg->state) {
+ sha256_hmac_drbg_free((SHA256_HMAC_DRBG_STATE *)drbg->state);
+ drbg->state = NULL;
+ }
+
+ drbg->handle = 0;
+ DRBG_RET(DRBG_OK);
+}
+
+
+/* ntru_crypto_drbg_reseed
+ *
+ * This routine reseeds an instantiated drbg.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ * Returns HMAC errors if they occur.
+ */
+
+uint32_t
+ntru_crypto_drbg_reseed(
+ DRBG_HANDLE handle) /* in - drbg handle */
+{
+ DRBG_STATE *drbg = NULL;
+
+ /* find the instantiated drbg */
+
+ if ((drbg = drbg_get_drbg(handle)) == NULL)
+ DRBG_RET(DRBG_BAD_PARAMETER);
+
+ /* reseed the SHA-256 HMAC_DRBG */
+
+ return sha256_hmac_drbg_reseed((SHA256_HMAC_DRBG_STATE *)drbg->state);
+}
+
+
+/* ntru_crypto_drbg_generate
+ *
+ * This routine generates pseudorandom bytes using an instantiated drbg.
+ * If the maximum number of requests has been reached, reseeding will occur.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid or if
+ * an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ * is too large or the number of bytes requested is zero or too large.
+ * Returns HMAC errors if they occur.
+ */
+
+uint32_t
+ntru_crypto_drbg_generate(
+ DRBG_HANDLE handle, /* in - drbg handle */
+ uint32_t sec_strength_bits, /* in - requested sec strength in bits */
+ uint32_t num_bytes, /* in - number of octets to generate */
+ uint8_t *out) /* out - address for generated octets */
+{
+ DRBG_STATE *drbg = NULL;
+
+ /* find the instantiated drbg */
+
+ if ((drbg = drbg_get_drbg(handle)) == NULL)
+ DRBG_RET(DRBG_BAD_PARAMETER);
+
+ /* check arguments */
+
+ if (!out)
+ DRBG_RET(DRBG_BAD_PARAMETER);
+ if (num_bytes == 0)
+ DRBG_RET(DRBG_BAD_LENGTH);
+
+ /* generate pseudorandom output from the SHA256_HMAC_DRBG */
+
+ return sha256_hmac_drbg_generate((SHA256_HMAC_DRBG_STATE *)drbg->state,
+ sec_strength_bits, num_bytes, out);
+}
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_drbg.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_drbg.h
+ *
+ * Contents: Public header file for ntru_crypto_drbg.c.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_DRBG_H
+#define NTRU_CRYPTO_DRBG_H
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_error.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 */
+
+#if defined ( __cplusplus )
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*******************
+ * DRBG parameters *
+ *******************/
+
+#if !defined(DRBG_MAX_INSTANTIATIONS)
+#define DRBG_MAX_INSTANTIATIONS 4
+#endif
+#define DRBG_MAX_SEC_STRENGTH_BITS 256
+#define DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY 8
+
+
+/************************
+ * HMAC_DRBG parameters *
+ ************************/
+
+#define HMAC_DRBG_MAX_PERS_STR_BYTES 32
+#define HMAC_DRBG_MAX_BYTES_PER_REQUEST 1024
+
+
+/********************
+ * type definitions *
+ ********************/
+
+typedef uint32_t DRBG_HANDLE; /* drbg handle */
+typedef enum { /* entropy-function commands */
+ GET_NUM_BYTES_PER_BYTE_OF_ENTROPY = 0,
+ INIT,
+ GET_BYTE_OF_ENTROPY,
+} ENTROPY_CMD;
+typedef uint8_t (*ENTROPY_FN)( /* get entropy function */
+ ENTROPY_CMD cmd, /* command */
+ uint8_t *out); /* address for output */
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define DRBG_OK 0x00000000 /* no errors */
+#define DRBG_OUT_OF_MEMORY 0x00000001 /* can't allocate memory */
+#define DRBG_BAD_PARAMETER 0x00000002 /* null pointer */
+#define DRBG_BAD_LENGTH 0x00000003 /* invalid no. of bytes */
+#define DRBG_NOT_AVAILABLE 0x00000004 /* no instantiation slot available */
+#define DRBG_ENTROPY_FAIL 0x00000005 /* entropy function failure */
+
+/***************
+ * error macro *
+ ***************/
+
+#define DRBG_RESULT(r) ((uint32_t)((r) ? DRBG_ERROR_BASE + (r) : (r)))
+#define DRBG_RET(r) return DRBG_RESULT(r);
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_drbg_instantiate
+ *
+ * This routine instantiates a drbg with the requested security strength.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ * or the personalization string is too large.
+ * Returns DRBG_ERROR_BASE + DRBG_OUT_OF_MEMORY if the internal state cannot be
+ * allocated from the heap.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_instantiate(
+ uint32_t sec_strength_bits, /* in - requested sec strength in bits */
+ uint8_t const *pers_str, /* in - ptr to personalization string */
+ uint32_t pers_str_bytes, /* in - no. personalization str bytes */
+ ENTROPY_FN entropy_fn, /* in - pointer to entropy function */
+ DRBG_HANDLE *handle); /* out - address for drbg handle */
+
+
+/* ntru_crypto_drbg_uninstantiate
+ *
+ * This routine frees a drbg given its handle.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_uninstantiate(
+ DRBG_HANDLE handle); /* in - drbg handle */
+
+
+/* ntru_crypto_drbg_reseed
+ *
+ * This routine reseeds an instantiated drbg.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ * Returns NTRU_CRYPTO_HMAC errors if they occur.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_reseed(
+ DRBG_HANDLE handle); /* in - drbg handle */
+
+
+/* ntru_crypto_drbg_generate
+ *
+ * This routine generates pseudorandom bytes using an instantiated drbg.
+ * If the maximum number of requests has been reached, reseeding will occur.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid or if
+ * an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ * is too large or the number of bytes requested is zero or too large.
+ * Returns NTRU_CRYPTO_HMAC errors if they occur.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_generate(
+ DRBG_HANDLE handle, /* in - drbg handle */
+ uint32_t sec_strength_bits, /* in - requested sec strength in bits */
+ uint32_t num_bytes, /* in - number of octets to generate */
+ uint8_t *out); /* out - address for generated octets */
+
+
+#if defined ( __cplusplus )
+}
+#endif /* __cplusplus */
+
+
+#endif /* NTRU_CRYPTO_DRBG_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_serror.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013 Security Innovation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *****************************************************************************/
+
+
+/******************************************************************************
+ *
+ * File: ntru_crypto_error.h
+ *
+ * Contents: Contains base values for crypto error codes.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_ERROR_H
+#define NTRU_CRYPTO_ERROR_H
+
+/* define base values for crypto error codes */
+
+#define HASH_ERROR_BASE ((uint32_t)0x00000100)
+#define HMAC_ERROR_BASE ((uint32_t)0x00000200)
+#define SHA_ERROR_BASE ((uint32_t)0x00000400)
+#define DRBG_ERROR_BASE ((uint32_t)0x00000a00)
+#define NTRU_ERROR_BASE ((uint32_t)0x00003000)
+#define MGF1_ERROR_BASE ((uint32_t)0x00004100)
+
+#endif /* NTRU_CRYPTO_ERROR_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_hash.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_hash.c
+ *
+ * Contents: Routines implementing the hash object abstraction.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include "ntru_crypto_hash.h"
+
+
+typedef uint32_t (*NTRU_CRYPTO_HASH_INIT_FN)(
+ void *c);
+typedef uint32_t (*NTRU_CRYPTO_HASH_UPDATE_FN)(
+ void *c,
+ void const *data,
+ uint32_t len);
+typedef uint32_t (*NTRU_CRYPTO_HASH_FINAL_FN)(
+ void *c,
+ void *md);
+typedef uint32_t (*NTRU_CRYPTO_HASH_DIGEST_FN)(
+ void const *data,
+ uint32_t len,
+ void *md);
+
+typedef struct _NTRU_CRYPTO_HASH_ALG_PARAMS {
+ uint8_t algid;
+ uint16_t block_length;
+ uint16_t digest_length;
+ NTRU_CRYPTO_HASH_INIT_FN init;
+ NTRU_CRYPTO_HASH_UPDATE_FN update;
+ NTRU_CRYPTO_HASH_FINAL_FN final;
+ NTRU_CRYPTO_HASH_FINAL_FN final_zero_pad;
+ NTRU_CRYPTO_HASH_DIGEST_FN digest;
+} NTRU_CRYPTO_HASH_ALG_PARAMS;
+
+static NTRU_CRYPTO_HASH_ALG_PARAMS const algs_params[] = {
+ {
+ NTRU_CRYPTO_HASH_ALGID_SHA1,
+ SHA_1_BLK_LEN,
+ SHA_1_MD_LEN,
+ (NTRU_CRYPTO_HASH_INIT_FN) SHA_1_INIT_FN,
+ (NTRU_CRYPTO_HASH_UPDATE_FN) SHA_1_UPDATE_FN,
+ (NTRU_CRYPTO_HASH_FINAL_FN) SHA_1_FINAL_FN,
+ (NTRU_CRYPTO_HASH_FINAL_FN) SHA_1_FINAL_ZERO_PAD_FN,
+ (NTRU_CRYPTO_HASH_DIGEST_FN) SHA_1_DIGEST_FN,
+ },
+ {
+ NTRU_CRYPTO_HASH_ALGID_SHA256,
+ SHA_256_BLK_LEN,
+ SHA_256_MD_LEN,
+ (NTRU_CRYPTO_HASH_INIT_FN) SHA_256_INIT_FN,
+ (NTRU_CRYPTO_HASH_UPDATE_FN) SHA_256_UPDATE_FN,
+ (NTRU_CRYPTO_HASH_FINAL_FN) SHA_256_FINAL_FN,
+ (NTRU_CRYPTO_HASH_FINAL_FN) SHA_256_FINAL_ZERO_PAD_FN,
+ (NTRU_CRYPTO_HASH_DIGEST_FN) SHA_256_DIGEST_FN,
+ },
+};
+
+static int const numalgs = (sizeof(algs_params)/sizeof(algs_params[0]));
+
+
+/* get_alg_params
+ *
+ * Return a pointer to the hash algorithm parameters for the hash algorithm
+ * specified, by looking for algid in the global algs_params table.
+ * If not found, return NULL.
+ */
+static NTRU_CRYPTO_HASH_ALG_PARAMS const *
+get_alg_params(
+ NTRU_CRYPTO_HASH_ALGID algid) // in - the hash algorithm to find
+{
+ int i;
+
+ for (i = 0; i < numalgs; i++)
+ if (algs_params[i].algid == algid)
+ return &algs_params[i];
+
+ return NULL;
+}
+
+
+/* ntru_crypto_hash_set_alg
+ *
+ * Sets the hash algorithm for the hash context. This must be called before
+ * any calls to ntru_crypto_hash_block_length(),
+ * ntru_crypto_hash_digest_length(), or ntru_crypto_hash_init() are made.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+uint32_t
+ntru_crypto_hash_set_alg(
+ NTRU_CRYPTO_HASH_ALGID algid, // in - hash algoirithm to be used
+ NTRU_CRYPTO_HASH_CTX *c) // in/out - pointer to the hash context
+{
+ if (!c)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ c->alg_params = get_alg_params(algid);
+ if (!c->alg_params) {
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+ }
+
+ HASH_RET(NTRU_CRYPTO_HASH_OK);
+}
+
+
+/* ntru_crypto_hash_block_length
+ *
+ * Gets the number of bytes in an input block for the hash algorithm
+ * specified in the hash context. The hash algorithm must have been set
+ * in the hash context with a call to ntru_crypto_hash_set_alg() prior to
+ * calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_block_length(
+ NTRU_CRYPTO_HASH_CTX *c, // in - pointer to the hash context
+ uint16_t *blk_len) // out - address for block length in bytes
+{
+ if (!c || !blk_len)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ if (!c->alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ *blk_len = c->alg_params->block_length;
+ HASH_RET(NTRU_CRYPTO_HASH_OK);
+}
+
+
+/* ntru_crypto_hash_digest_length
+ *
+ * Gets the number of bytes needed to hold the message digest for the
+ * hash algorithm specified in the hash context. The algorithm must have
+ * been set in the hash context with a call to ntru_crypto_hash_set_alg() prior
+ * to calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_digest_length(
+ NTRU_CRYPTO_HASH_CTX const *c, // in - pointer to the hash context
+ uint16_t *md_len) // out - addr for digest length in bytes
+{
+ if (!c || !md_len)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ if (!c->alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ *md_len = c->alg_params->digest_length;
+ HASH_RET(NTRU_CRYPTO_HASH_OK);
+}
+
+
+/* ntru_crypto_hash_init
+ *
+ * This routine performs standard initialization of the hash state.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_init(
+ NTRU_CRYPTO_HASH_CTX *c) // in/out - pointer to hash context
+{
+ if (!c)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ if (!c->alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ return c->alg_params->init(&c->alg_ctx);
+}
+
+
+/* ntru_crypto_hash_update
+ *
+ * This routine processes input data and updates the hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ * hash algorithm. The size limit is dependent on the hash algorithm,
+ * and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_update(
+ NTRU_CRYPTO_HASH_CTX *c, // in/out - pointer to hash context
+ uint8_t const *data, // in - pointer to input data
+ uint32_t data_len) // in - number of bytes of input data
+{
+ if (!c || (data_len && !data))
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ if (!c->alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ return c->alg_params->update(&c->alg_ctx, data, data_len);
+}
+
+
+/* ntru_crypto_hash_final
+ *
+ * This routine completes the hash calculation and returns the message digest.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_final(
+ NTRU_CRYPTO_HASH_CTX *c, // in/out - pointer to hash context
+ uint8_t *md) // out - address for message digest
+{
+ if (!c || !md)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ if (!c->alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ return c->alg_params->final(&c->alg_ctx, md);
+}
+
+
+/* ntru_crypto_hash_final_zero_pad
+ *
+ * This routine completes the hash calculation using zero padding and
+ * returns the message digest.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_final_zero_pad(
+ NTRU_CRYPTO_HASH_CTX *c, // in/out - pointer to hash context
+ uint8_t *md) // out - address for message digest
+{
+ if (!c || !md)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ if (!c->alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ return c->alg_params->final_zero_pad(&c->alg_ctx, md);
+}
+
+
+/* ntru_crypto_hash_digest
+ *
+ * This routine computes a message digest. It is assumed that the
+ * output buffer md is large enough to hold the output (see
+ * ntru_crypto_hash_digest_length)
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ * hash algorithm. The size limit is dependent on the hash algorithm,
+ * and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+uint32_t
+ntru_crypto_hash_digest(
+ NTRU_CRYPTO_HASH_ALGID algid, // in - the hash algorithm to use
+ uint8_t const *data, // in - pointer to input data
+ uint32_t data_len, // in - number of bytes of input data
+ uint8_t *md) // out - address for message digest
+{
+ NTRU_CRYPTO_HASH_ALG_PARAMS const *alg_params = get_alg_params(algid);
+
+ if (!alg_params)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+ if ((data_len && !data) || !md)
+ HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+ return alg_params->digest(data, data_len, md);
+}
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_hash.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_hash.h
+ *
+ * Contents: Definitions and declarations for the hash object abstraction.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_HASH_H
+#define NTRU_CRYPTO_HASH_H
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_error.h"
+#include "ntru_crypto_hash_basics.h"
+#include "ntru_crypto_sha1.h"
+#include "ntru_crypto_sha256.h"
+
+
+/***************
+ * error macro *
+ ***************/
+
+#define HASH_RESULT(r) ((uint32_t)((r) ? HASH_ERROR_BASE + (r) : (r)))
+#define HASH_RET(r) return HASH_RESULT(r);
+
+
+/*************************
+ * structure definitions *
+ *************************/
+
+/* _NTRU_CRYPTO_HASH_ALG_PARAMS
+ *
+ * An opaque forward declaration for a private structure used
+ * internally by the hash object interface.
+ */
+
+struct _NTRU_CRYPTO_HASH_ALG_PARAMS;
+
+
+/* NTRU_CRYPTO_HASH_CTX
+ *
+ * Hash object context information.
+ */
+
+typedef struct {
+ struct _NTRU_CRYPTO_HASH_ALG_PARAMS const *alg_params;
+ union {
+ NTRU_CRYPTO_SHA1_CTX sha1;
+ NTRU_CRYPTO_SHA2_CTX sha256;
+ } alg_ctx;
+} NTRU_CRYPTO_HASH_CTX;
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_hash_set_alg
+ *
+ * Sets the hash algorithm for the hash context. This must be called before
+ * any calls to crypto_hash_block_length(), crypto_hash_digest_length(), or
+ * crypto_hash_init() are made.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+extern uint32_t
+ntru_crypto_hash_set_alg(
+ NTRU_CRYPTO_HASH_ALGID algid, // in - hash algoirithm to be used
+ NTRU_CRYPTO_HASH_CTX *c); // in/out - pointer to the hash context
+
+
+/* ntru_crypto_hash_block_length
+ *
+ * Gets the number of bytes in an input block for the hash algorithm
+ * specified in the hash context. The hash algorithm must have been set
+ * in the hash context with a call to crypto_hash_set_alg() prior to
+ * calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_block_length(
+ NTRU_CRYPTO_HASH_CTX *c, // in - pointer to the hash context
+ uint16_t *blk_len); // out - address for block length in bytes
+
+
+/* ntru_crypto_hash_digest_length
+ *
+ * Gets the number of bytes needed to hold the message digest for the
+ * hash algorithm specified in the hash context. The algorithm must have
+ * been set in the hash context with a call to crypto_hash_set_alg() prior
+ * to calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_digest_length(
+ NTRU_CRYPTO_HASH_CTX const *c, // in - pointer to the hash context
+ uint16_t *md_len); // out - addrfor digest length in bytes
+
+
+/* ntru_crypto_hash_init
+ *
+ * This routine initializes the hash state.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_init(
+ NTRU_CRYPTO_HASH_CTX *c); // in/out - pointer to hash context
+
+
+/* ntru_crypto_hash_update
+ *
+ * This routine processes input data and updates the hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ * hash algorithm. The size limit is dependent on the hash algorithm,
+ * and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_update(
+ NTRU_CRYPTO_HASH_CTX *c, // in/out - pointer to hash context
+ uint8_t const *data, // in - pointer to input data
+ uint32_t data_len); // in - number of bytes of input data
+
+
+/* ntru_crypto_hash_final
+ *
+ * This routine completes the hash calculation and returns the message digest.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_final(
+ NTRU_CRYPTO_HASH_CTX *c, // in/out - pointer to hash context
+ uint8_t *md); // out - address for message digest
+
+
+/* ntru_crypto_hash_final_zero_pad
+ *
+ * This routine completes the hash calculation using zero padding and
+ * returns the message digest.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_final_zero_pad(
+ NTRU_CRYPTO_HASH_CTX *c, // in/out - pointer to hash context
+ uint8_t *md); // out - address for message digest
+
+
+/* ntru_crypto_hash_digest
+ *
+ * This routine computes a message digest. It is assumed that the
+ * output buffer md is large enough to hold the output (see
+ * crypto_hash_digest_length)
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ * hash algorithm. The size limit is dependent on the hash algorithm,
+ * and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+extern uint32_t
+ntru_crypto_hash_digest(
+ NTRU_CRYPTO_HASH_ALGID algid, // in - the hash algorithm to use
+ uint8_t const *data, // in - pointer to input data
+ uint32_t data_len, // in - number of bytes of input data
+ uint8_t *md); // out - address for message digest
+
+
+#endif /* NTRU_CRYPTO_HASH_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_hash_basics.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_hash_basics.h
+ *
+ * Contents: Common definitions for all hash algorithms.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_HASH_BASICS_H
+#define NTRU_CRYPTO_HASH_BASICS_H
+
+#include "ntru_crypto_platform.h"
+
+
+/**************
+ * algorithms *
+ **************/
+
+typedef enum {
+ NTRU_CRYPTO_HASH_ALGID_NONE = 0,
+ NTRU_CRYPTO_HASH_ALGID_SHA1,
+ NTRU_CRYPTO_HASH_ALGID_SHA256,
+} NTRU_CRYPTO_HASH_ALGID;
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define NTRU_CRYPTO_HASH_OK ((uint32_t)0x00)
+#define NTRU_CRYPTO_HASH_FAIL ((uint32_t)0x01)
+#define NTRU_CRYPTO_HASH_BAD_PARAMETER ((uint32_t)0x02)
+#define NTRU_CRYPTO_HASH_OVERFLOW ((uint32_t)0x03)
+#define NTRU_CRYPTO_HASH_BAD_ALG ((uint32_t)0x20)
+#define NTRU_CRYPTO_HASH_OUT_OF_MEMORY ((uint32_t)0x21)
+
+// For backward-compatibility
+typedef uint32_t NTRU_CRYPTO_HASH_ERROR;
+
+
+/*********
+ * flags *
+ *********/
+
+#define HASH_DATA_ONLY 0
+#define HASH_INIT (1 << 0)
+#define HASH_FINISH (1 << 1)
+#define HASH_ZERO_PAD (1 << 2)
+
+
+#endif /* NTRU_CRYPTO_HASH_BASICS_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_hmac.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_hmac.c
+ *
+ * Contents: Routines implementing the HMAC hash calculation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_hmac.h"
+
+
+/* HMAC context */
+
+struct _NTRU_CRYPTO_HMAC_CTX {
+ NTRU_CRYPTO_HASH_CTX hash_ctx;
+ uint8_t *k0;
+ uint16_t blk_len;
+ uint16_t md_len;
+};
+
+
+/* ntru_crypto_hmac_create_ctx
+ *
+ * This routine creates an HMAC context, setting the hash algorithm and
+ * the key to be used.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_ALG if the specified algorithm is not supported.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HMAC_OUT_OF_MEMORY if memory cannot be allocated.
+ */
+
+uint32_t
+ntru_crypto_hmac_create_ctx(
+ NTRU_CRYPTO_HASH_ALGID algid, /* in - the hash algorithm to be used */
+ uint8_t const *key, /* in - pointer to the HMAC key */
+ uint32_t key_len, /* in - number of bytes in HMAC key */
+ NTRU_CRYPTO_HMAC_CTX **c) /* out - address for pointer to HMAC
+ context */
+{
+ NTRU_CRYPTO_HMAC_CTX *ctx = NULL;
+ uint32_t result;
+
+ /* check parameters */
+
+ if (!c || !key)
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ *c = NULL;
+
+ /* allocate memory for an HMAC context */
+
+ if ((ctx = (NTRU_CRYPTO_HMAC_CTX*) malloc(sizeof(NTRU_CRYPTO_HMAC_CTX))) ==
+ NULL)
+ HMAC_RET(NTRU_CRYPTO_HMAC_OUT_OF_MEMORY);
+
+ /* set the algorithm */
+
+ if (result = ntru_crypto_hash_set_alg(algid, &ctx->hash_ctx)) {
+ free(ctx);
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_ALG);
+ }
+
+ /* set block length and digest length */
+
+ if ((result = ntru_crypto_hash_block_length(&ctx->hash_ctx,
+ &ctx->blk_len)) ||
+ (result = ntru_crypto_hash_digest_length(&ctx->hash_ctx,
+ &ctx->md_len))) {
+ free(ctx);
+ return result;
+ }
+
+ /* allocate memory for K0 */
+
+ if ((ctx->k0 = (uint8_t*) malloc(ctx->blk_len)) == NULL) {
+ free(ctx);
+ HMAC_RET(NTRU_CRYPTO_HMAC_OUT_OF_MEMORY);
+ }
+
+ /* calculate K0 and store in HMAC context */
+
+ memset(ctx->k0, 0, ctx->blk_len);
+
+ /* check if key is too large */
+
+ if (key_len > ctx->blk_len) {
+
+ if (result = ntru_crypto_hash_digest(algid, key, key_len, ctx->k0)) {
+ memset(ctx->k0, 0, ctx->blk_len);
+ free(ctx->k0);
+ free(ctx);
+ return result;
+ }
+
+ } else
+ memcpy(ctx->k0, key, key_len);
+
+ /* return pointer to HMAC context */
+
+ *c = ctx;
+ HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_destroy_ctx
+ *
+ * Destroys an HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_destroy_ctx(
+ NTRU_CRYPTO_HMAC_CTX *c) /* in/out - pointer to HMAC context */
+{
+ if (!c || !c->k0)
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ /* clear key and release memory */
+
+ memset(c->k0, 0, c->blk_len);
+ free(c->k0);
+ free(c);
+
+ HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_get_md_len
+ *
+ * This routine gets the digest length of the HMAC.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_get_md_len(
+ NTRU_CRYPTO_HMAC_CTX const *c, /* in - pointer to HMAC context */
+ uint16_t *md_len) /* out - address for digest length */
+{
+ /* check parameters */
+
+ if (!c || !md_len)
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ /* get digest length */
+
+ *md_len = c->md_len;
+ HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_set_key
+ *
+ * This routine sets a digest-length key into the HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_set_key(
+ NTRU_CRYPTO_HMAC_CTX *c, /* in - pointer to HMAC context */
+ uint8_t const *key) /* in - pointer to new HMAC key */
+{
+ /* check parameters */
+
+ if (!c || !key)
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ /* copy key */
+
+ memcpy(c->k0, key, c->md_len);
+ HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_init
+ *
+ * This routine performs standard initialization of the HMAC state.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_init(
+ NTRU_CRYPTO_HMAC_CTX *c) /* in/out - pointer to HMAC context */
+{
+ uint32_t result;
+ int i;
+
+ /* check parameters */
+
+ if (!c)
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ /* init hash context and compute H(K0 ^ ipad) */
+
+ for (i = 0; i < c->blk_len; i++)
+ c->k0[i] ^= 0x36; /* K0 ^ ipad */
+ if ((result = ntru_crypto_hash_init(&c->hash_ctx)) ||
+ (result = ntru_crypto_hash_update(&c->hash_ctx, c->k0, c->blk_len)))
+ return result;
+
+ HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_update
+ *
+ * This routine processes input data and updates the HMAC hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if more than bytes are hashed than the
+ * underlying hash algorithm can handle.
+ */
+
+uint32_t
+ntru_crypto_hmac_update(
+ NTRU_CRYPTO_HMAC_CTX *c, /* in/out - pointer to HMAC context */
+ const uint8_t *data, /* in - pointer to input data */
+ uint32_t data_len) /* in - no. of bytes of input data */
+{
+ uint32_t result;
+
+ /* check parameters */
+
+ if (!c || (data_len && !data))
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ if (result = ntru_crypto_hash_update(&c->hash_ctx, data, data_len))
+ return result;
+
+ HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_final
+ *
+ * This routine completes the HMAC hash calculation and returns the
+ * message digest.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_final(
+ NTRU_CRYPTO_HMAC_CTX *c, /* in/out - pointer to HMAC context */
+ uint8_t *md) /* out - address for message digest */
+{
+ uint32_t result = NTRU_CRYPTO_HMAC_OK;
+ int i;
+
+ /* check parameters */
+
+ if (!c || !md)
+ HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+ /* form K0 ^ opad
+ * complete md = H((K0 ^ ipad) || data)
+ * compute md = H((K0 ^ opad) || md)
+ * re-form K0
+ */
+
+ for (i = 0; i < c->blk_len; i++)
+ c->k0[i] ^= (0x36^0x5c);
+ if ((result = ntru_crypto_hash_final(&c->hash_ctx, md)) ||
+ (result = ntru_crypto_hash_init(&c->hash_ctx)) ||
+ (result = ntru_crypto_hash_update(&c->hash_ctx, c->k0, c->blk_len)) ||
+ (result = ntru_crypto_hash_update(&c->hash_ctx, md, c->md_len)) ||
+ (result = ntru_crypto_hash_final(&c->hash_ctx, md))) {
+ }
+ for (i = 0; i < c->blk_len; i++)
+ c->k0[i] ^= 0x5c;
+ return result;
+}
+
--- /dev/null
+/*/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_hmac.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_hmac.h
+ *
+ * Contents: Definitions and declarations for the HMAC implementation.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_HMAC_H
+#define NTRU_CRYPTO_HMAC_H
+
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_hash.h"
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define NTRU_CRYPTO_HMAC_OK ((uint32_t)NTRU_CRYPTO_HASH_OK)
+#define NTRU_CRYPTO_HMAC_BAD_PARAMETER ((uint32_t)NTRU_CRYPTO_HASH_BAD_PARAMETER)
+#define NTRU_CRYPTO_HMAC_BAD_ALG ((uint32_t)NTRU_CRYPTO_HASH_BAD_ALG)
+#define NTRU_CRYPTO_HMAC_OUT_OF_MEMORY ((uint32_t)NTRU_CRYPTO_HASH_OUT_OF_MEMORY)
+
+#define HMAC_RESULT(e) ((uint32_t)((e) ? HMAC_ERROR_BASE + (e) : (e)))
+#define HMAC_RET(e) return HMAC_RESULT(e)
+
+
+/*************************
+ * structure definitions *
+ *************************/
+
+/* HMAC context structure */
+
+struct _NTRU_CRYPTO_HMAC_CTX; /* opaque forward reference */
+typedef struct _NTRU_CRYPTO_HMAC_CTX NTRU_CRYPTO_HMAC_CTX;
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_hmac_create_ctx
+ *
+ * This routine creates an HMAC context, setting the hash algorithm and
+ * the key to be used.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OUT_OF_MEMORY if memory cannot be allocated.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_create_ctx(
+ NTRU_CRYPTO_HASH_ALGID algid, /* in - the hash algorithm to be used */
+ uint8_t const *key, /* in - pointer to the HMAC key */
+ uint32_t key_len, /* in - number of bytes in HMAC key */
+ NTRU_CRYPTO_HMAC_CTX **c); /* out - address for pointer to HMAC
+ context */
+
+
+/* ntru_crypto_hmac_destroy_ctx
+ *
+ * Destroys an HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_destroy_ctx(
+ NTRU_CRYPTO_HMAC_CTX *c); /* in/out - pointer to HMAC context */
+
+
+/* ntru_crypto_hmac_get_md_len
+ *
+ * This routine gets the digest length of the HMAC.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_get_md_len(
+ NTRU_CRYPTO_HMAC_CTX const *c, /* in - pointer to HMAC context */
+ uint16_t *md_len); /* out - address for digest length */
+
+
+/* ntru_crypto_hmac_set_key
+ *
+ * This routine sets a digest-length key into the HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_set_key(
+ NTRU_CRYPTO_HMAC_CTX *c, /* in - pointer to HMAC context */
+ uint8_t const *key); /* in - pointer to new HMAC key */
+
+
+/* ntru_crypto_hmac_init
+ *
+ * This routine performs standard initialization of the HMAC state.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_init(
+ NTRU_CRYPTO_HMAC_CTX *c); /* in/out - pointer to HMAC context */
+
+
+/* ntru_crypto_hmac_update
+ *
+ * This routine processes input data and updates the HMAC hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HMAC_OVERFLOW if more than bytes are hashed than the underlying
+ * hash algorithm can handle.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_update(
+ NTRU_CRYPTO_HMAC_CTX *c, /* in/out - pointer to HMAC context */
+ uint8_t const *data, /* in - pointer to input data */
+ uint32_t data_len); /* in - no. of bytes of input data */
+
+
+/* ntru_crypto_hmac_final
+ *
+ * This routine completes the HMAC hash calculation and returns the
+ * message digest.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_final(
+ NTRU_CRYPTO_HMAC_CTX *c, /* in/out - pointer to HMAC context */
+ uint8_t *md); /* out - address for message digest */
+
+
+#endif /* NTRU_CRYPTO_HMAC_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_mbyte_uint32.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_msbyte_uint32.c
+ *
+ * Contents: Routines to convert between an array of bytes in network byte
+ * order (most-significant byte first) and an array of uint32 words.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include "ntru_crypto_msbyte_uint32.h"
+
+
+/* ntru_crypto_msbyte_2_uint32()
+ *
+ * This routine converts an array of bytes in network byte order to an array
+ * of uint32_t, placing the first byte in the most significant byte of the
+ * first uint32_t word.
+ *
+ * The number of bytes in the input stream MUST be at least 4 times the
+ * number of words expected in the output array.
+ */
+
+void
+ntru_crypto_msbyte_2_uint32(
+ uint32_t *words, // out - pointer to the output uint32_t array
+ uint8_t const *bytes, // in - pointer to the input byte array
+ uint32_t n) // in - number of words in the output array
+{
+ uint32_t i;
+
+ for (i = 0; i < n; i++) {
+ words[i] = ((uint32_t) (*bytes++)) << 24;
+ words[i] |= ((uint32_t) (*bytes++)) << 16;
+ words[i] |= ((uint32_t) (*bytes++)) << 8;
+ words[i] |= (uint32_t) (*bytes++);
+ }
+}
+
+
+/* ntru_crypto_uint32_2_msbyte()
+ *
+ * This routine converts an array of uint32_t to an array of bytes in
+ * network byte order, placing the most significant byte of the first uint32_t
+ * word as the first byte of the output array.
+ *
+ * The number of bytes in the output stream will be 4 times the number of words
+ * specified in the input array.
+ */
+
+void
+ntru_crypto_uint32_2_msbyte(
+ uint8_t *bytes, // out - pointer to the output byte array
+ uint32_t const *words, // in - pointer to the input uint32_t array
+ uint32_t n) // in - number of words in the input array
+{
+ uint32_t i;
+
+ for (i = 0; i < n; i++) {
+ *bytes++ = (uint8_t) (words[i] >> 24);
+ *bytes++ = (uint8_t) (words[i] >> 16);
+ *bytes++ = (uint8_t) (words[i] >> 8);
+ *bytes++ = (uint8_t) (words[i] );
+ }
+}
+
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_msbyte_uint32.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_msbyte_uint32.h
+ *
+ * Contents: Definitions and declarations for converting between a most-
+ * significant-first byte stream and a uint32_t array.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_MSBYTE_UINT32_H
+#define NTRU_CRYPTO_MSBYTE_UINT32_H
+
+
+#include "ntru_crypto_platform.h"
+
+
+/* ntru_crypto_msbyte_2_uint32()
+ *
+ * This routine converts an array of bytes in network byte order to an array
+ * of uint32_t, placing the first byte in the most significant byte of the
+ * first uint32_t word.
+ *
+ * The number of bytes in the input stream MUST be at least 4 times the
+ * number of words expected in the output array.
+ */
+
+extern void
+ntru_crypto_msbyte_2_uint32(
+ uint32_t *words, // out - pointer to the output uint32_t array
+ uint8_t const *bytes, // in - pointer to the input byte array
+ uint32_t n); // in - number of words in the output array
+
+
+/* ntru_crypto_uint32_2_msbyte()
+ *
+ * This routine converts an array of uint32_t to an array of bytes in
+ * network byte order, placing the most significant byte of the first uint32_t
+ * word as the first byte of the output array.
+ *
+ * The number of bytes in the output stream will be 4 times the number of words
+ * specified in the input array.
+ */
+
+extern void
+ntru_crypto_uint32_2_msbyte(
+ uint8_t *bytes, // out - pointer to the output byte array
+ uint32_t const *words, // in - pointer to the input uint32_t array
+ uint32_t n); // in - number of words in the input array
+
+
+#endif /* NTRU_CRYPTO_MSBYTE_UINT32_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_convert.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013 Security Innovation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_convert.c
+ *
+ * Contents: Conversion routines for NTRUEncrypt, including packing, unpacking,
+ * and others.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_convert.h"
+
+
+/* 3-bit to 2-trit conversion tables: 2 represents -1 */
+
+static uint8_t const bits_2_trit1[] = {0, 0, 0, 1, 1, 1, 2, 2};
+static uint8_t const bits_2_trit2[] = {0, 1, 2, 0, 1, 2, 0, 1};
+
+
+/* ntru_bits_2_trits
+ *
+ * Each 3 bits in an array of octets is converted to 2 trits in an array
+ * of trits.
+ *
+ * The octet array may overlap the end of the trit array.
+ */
+
+void
+ntru_bits_2_trits(
+ uint8_t const *octets, /* in - pointer to array of octets */
+ uint16_t num_trits, /* in - number of trits to produce */
+ uint8_t *trits) /* out - address for array of trits */
+{
+ uint32_t bits24;
+ uint32_t bits3;
+ uint32_t shift;
+
+ assert(octets);
+ assert(trits);
+
+ while (num_trits >= 16) {
+
+ /* get next three octets */
+
+ bits24 = ((uint32_t)(*octets++)) << 16;
+ bits24 |= ((uint32_t)(*octets++)) << 8;
+ bits24 |= (uint32_t)(*octets++);
+
+ /* for each 3 bits in the three octets, output 2 trits */
+
+ bits3 = (bits24 >> 21) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = (bits24 >> 18) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = (bits24 >> 15) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = (bits24 >> 12) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = (bits24 >> 9) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = (bits24 >> 6) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = (bits24 >> 3) & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ bits3 = bits24 & 0x7;
+ *trits++ = bits_2_trit1[bits3];
+ *trits++ = bits_2_trit2[bits3];
+
+ num_trits -= 16;
+ }
+ if (num_trits == 0)
+ return;
+
+ /* get three octets */
+
+ bits24 = ((uint32_t)(*octets++)) << 16;
+ bits24 |= ((uint32_t)(*octets++)) << 8;
+ bits24 |= (uint32_t)(*octets++);
+
+ shift = 21;
+ while (num_trits) {
+
+ /* for each 3 bits in the three octets, output up to 2 trits
+ * until all trits needed are produced
+ */
+
+ bits3 = (bits24 >> shift) & 0x7;
+ shift -= 3;
+ *trits++ = bits_2_trit1[bits3];
+ if (--num_trits) {
+ *trits++ = bits_2_trit2[bits3];
+ --num_trits;
+ }
+ }
+}
+
+
+/* ntru_trits_2_bits
+ *
+ * Each 2 trits in an array of trits is converted to 3 bits, and the bits
+ * are packed in an array of octets. A multiple of 3 octets is output.
+ * Any bits in the final octets not derived from trits are zero.
+ *
+ * Returns TRUE if all trits were valid.
+ * Returns FALSE if invalid trits were found.
+ */
+
+bool
+ntru_trits_2_bits(
+ uint8_t const *trits, /* in - pointer to array of trits */
+ uint32_t num_trits, /* in - number of trits to convert */
+ uint8_t *octets) /* out - address for array of octets */
+{
+ bool all_trits_valid = TRUE;
+ uint32_t bits24;
+ uint32_t bits3;
+ uint32_t shift;
+
+ assert(octets);
+ assert(trits);
+
+ while (num_trits >= 16) {
+
+ /* convert each 2 trits to 3 bits and pack */
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 = (bits3 << 21);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << 18);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << 15);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << 12);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << 9);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << 6);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << 3);
+
+ bits3 = *trits++ * 3;
+ bits3 += *trits++;
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= bits3;
+
+ num_trits -= 16;
+
+ /* output three octets */
+
+ *octets++ = (uint8_t)((bits24 >> 16) & 0xff);
+ *octets++ = (uint8_t)((bits24 >> 8) & 0xff);
+ *octets++ = (uint8_t)(bits24 & 0xff);
+ }
+
+ bits24 = 0;
+ shift = 21;
+ while (num_trits) {
+
+ /* convert each 2 trits to 3 bits and pack */
+
+ bits3 = *trits++ * 3;
+ if (--num_trits) {
+ bits3 += *trits++;
+ --num_trits;
+ }
+ if (bits3 > 7) {
+ bits3 = 7;
+ all_trits_valid = FALSE;
+ }
+ bits24 |= (bits3 << shift);
+ shift -= 3;
+ }
+
+ /* output three octets */
+
+ *octets++ = (uint8_t)((bits24 >> 16) & 0xff);
+ *octets++ = (uint8_t)((bits24 >> 8) & 0xff);
+ *octets++ = (uint8_t)(bits24 & 0xff);
+
+ return all_trits_valid;
+}
+
+
+/* ntru_coeffs_mod4_2_octets
+ *
+ * Takes an array of ring element coefficients mod 4 and packs the
+ * results into an octet string.
+ */
+
+void
+ntru_coeffs_mod4_2_octets(
+ uint16_t num_coeffs, /* in - number of coefficients */
+ uint16_t const *coeffs, /* in - pointer to coefficients */
+ uint8_t *octets) /* out - address for octets */
+{
+ uint8_t bits2;
+ int shift;
+ uint16_t i;
+
+ assert(coeffs);
+ assert(octets);
+
+ *octets = 0;
+ shift = 6;
+ for (i = 0; i < num_coeffs; i++) {
+ bits2 = (uint8_t)(coeffs[i] & 0x3);
+ *octets |= bits2 << shift;
+ shift -= 2;
+ if (shift < 0) {
+ ++octets;
+ *octets = 0;
+ shift = 6;
+ }
+ }
+}
+
+
+/* ntru_trits_2_octet
+ *
+ * Packs 5 trits in an octet, where a trit is 0, 1, or 2 (-1).
+ */
+
+void
+ntru_trits_2_octet(
+ uint8_t const *trits, /* in - pointer to trits */
+ uint8_t *octet) /* out - address for octet */
+{
+ int i;
+
+ assert(trits);
+ assert(octet);
+
+ *octet = 0;
+ for (i = 4; i >= 0; i--) {
+ *octet = (*octet * 3) + trits[i];
+ }
+}
+
+
+/* ntru_octet_2_trits
+ *
+ * Unpacks an octet to 5 trits, where a trit is 0, 1, or 2 (-1).
+ */
+
+void
+ntru_octet_2_trits(
+ uint8_t octet, /* in - octet to be unpacked */
+ uint8_t *trits) /* out - address for trits */
+{
+ int i;
+
+ assert(trits);
+
+ for (i = 0; i < 5; i++) {
+ trits[i] = octet % 3;
+ octet = (octet - trits[i]) / 3;
+ }
+}
+
+
+/* ntru_indices_2_trits
+ *
+ * Converts a list of the nonzero indices of a polynomial into an array of
+ * trits.
+ */
+
+void
+ntru_indices_2_trits(
+ uint16_t in_len, /* in - no. of indices */
+ uint16_t const *in, /* in - pointer to list of indices */
+ bool plus1, /* in - if list is +1 cofficients */
+ uint8_t *out) /* out - address of output polynomial */
+{
+ uint8_t trit = plus1 ? 1 : 2;
+ uint16_t i;
+
+ assert(in);
+ assert(out);
+
+ for (i = 0; i < in_len; i++) {
+ out[in[i]] = trit;
+ }
+}
+
+
+/* ntru_packed_trits_2_indices
+ *
+ * Unpacks an array of N trits and creates a list of array indices
+ * corresponding to trits = +1, and list of array indices corresponding to
+ * trits = -1.
+ */
+
+void
+ntru_packed_trits_2_indices(
+ uint8_t const *in, /* in - pointer to packed-trit octets */
+ uint16_t num_trits, /* in - no. of packed trits */
+ uint16_t *indices_plus1, /* out - address for indices of +1 trits */
+ uint16_t *indices_minus1) /* out - address for indices of -1 trits */
+{
+ uint8_t trits[5];
+ uint16_t i = 0;
+ int j;
+
+ assert(in);
+ assert(indices_plus1);
+ assert(indices_minus1);
+
+ while (num_trits >= 5) {
+ ntru_octet_2_trits(*in++, trits);
+ num_trits -= 5;
+ for (j = 0; j < 5; j++, i++) {
+ if (trits[j] == 1) {
+ *indices_plus1 = i;
+ ++indices_plus1;
+ } else if (trits[j] == 2) {
+ *indices_minus1 = i;
+ ++indices_minus1;
+ }
+ }
+ }
+ if (num_trits) {
+ ntru_octet_2_trits(*in, trits);
+ for (j = 0; num_trits && (j < 5); j++, i++) {
+ if (trits[j] == 1) {
+ *indices_plus1 = i;
+ ++indices_plus1;
+ } else if (trits[j] == 2) {
+ *indices_minus1 = i;
+ ++indices_minus1;
+ }
+ --num_trits;
+ }
+ }
+}
+
+
+/* ntru_indices_2_packed_trits
+ *
+ * Takes a list of array indices corresponding to elements whose values
+ * are +1 or -1, and packs the N-element array of trits described by these
+ * lists into octets, 5 trits per octet.
+ */
+
+void
+ntru_indices_2_packed_trits(
+ uint16_t const *indices, /* in - pointer to indices */
+ uint16_t num_plus1, /* in - no. of indices for +1 trits */
+ uint16_t num_minus1, /* in - no. of indices for -1 trits */
+ uint16_t num_trits, /* in - N, no. of trits in array */
+ uint8_t *buf, /* in - temp buf, N octets */
+ uint8_t *out) /* out - address for packed octets */
+{
+ assert(indices);
+ assert(buf);
+ assert(out);
+
+ /* convert indices to an array of trits */
+
+ memset(buf, 0, num_trits);
+ ntru_indices_2_trits(num_plus1, indices, TRUE, buf);
+ ntru_indices_2_trits(num_minus1, indices + num_plus1, FALSE, buf);
+
+ /* pack the array of trits */
+
+ while (num_trits >= 5) {
+ ntru_trits_2_octet(buf, out);
+ num_trits -= 5;
+ buf += 5;
+ ++out;
+ }
+ if (num_trits) {
+ uint8_t trits[5];
+
+ memcpy(trits, buf, num_trits);
+ memset(trits + num_trits, 0, sizeof(trits) - num_trits);
+ ntru_trits_2_octet(trits, out);
+ }
+}
+
+
+/* ntru_elements_2_octets
+ *
+ * Packs an array of n-bit elements into an array of
+ * ((in_len * n_bits) + 7) / 8 octets, 8 < n_bits < 16.
+ */
+
+void
+ntru_elements_2_octets(
+ uint16_t in_len, /* in - no. of elements to be packed */
+ uint16_t const *in, /* in - ptr to elements to be packed */
+ uint8_t n_bits, /* in - no. of bits in input element */
+ uint8_t *out) /* out - addr for output octets */
+{
+ uint16_t temp;
+ int shift;
+ uint16_t i;
+
+ assert(in_len);
+ assert(in);
+ assert((n_bits > 8) && (n_bits < 16));
+ assert(out);
+
+ /* pack */
+
+ temp = 0;
+ shift = n_bits - 8;
+ i = 0;
+ while (i < in_len) {
+
+ /* add bits to temp to fill an octet and output the octet */
+
+ temp |= in[i] >> shift;
+ *out++ = (uint8_t)(temp & 0xff);
+ shift = 8 - shift;
+ if (shift < 1) {
+
+ /* next full octet is in current input word */
+
+ shift += n_bits;
+ temp = 0;
+
+ } else {
+
+ /* put remaining bits of input word in temp as partial octet,
+ * and increment index to next input word
+ */
+ temp = in[i] << (uint16_t)shift;
+
+ ++i;
+ }
+ shift = n_bits - shift;
+ }
+
+ /* output any bits remaining in last input word */
+
+ if (shift != n_bits - 8) {
+ *out++ = (uint8_t)(temp & 0xff);
+ }
+}
+
+
+/* ntru_octets_2_elements
+ *
+ * Unpacks an octet string into an array of ((in_len * 8) / n_bits)
+ * n-bit elements, 8 < n_bits < 16. Any extra bits are discarded.
+ */
+
+void
+ntru_octets_2_elements(
+ uint16_t in_len, /* in - no. of octets to be unpacked */
+ uint8_t const *in, /* in - ptr to octets to be unpacked */
+ uint8_t n_bits, /* in - no. of bits in output element */
+ uint16_t *out) /* out - addr for output elements */
+{
+ uint16_t temp;
+ uint16_t mask = (1 << n_bits) - 1;
+ int shift;
+ uint16_t i;
+
+ assert(in_len > 1);
+ assert(in);
+ assert((n_bits > 8) && (n_bits < 16));
+ assert(out);
+
+ /* unpack */
+
+ temp = 0;
+ shift = n_bits;
+ i = 0;
+ while (i < in_len) {
+ shift = 8 - shift;
+ if (shift < 0) {
+
+ /* the current octet will not fill the current element */
+
+ shift += n_bits;
+
+ } else {
+
+ /* add bits from the current octet to fill the current element and
+ * output the element
+ */
+
+ temp |= ((uint16_t)in[i]) >> shift;
+ *out++ = temp & mask;
+ temp = 0;
+ }
+
+ /* add the remaining bits of the current octet to start an element */
+
+ shift = n_bits - shift;
+ temp |= ((uint16_t)in[i]) << shift;
+ ++i;
+ }
+}
+
+
--- /dev/null
+/******************************************************************************
+ * 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 */
+
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_encrypt.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013 Security Innovation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_encrypt.c
+ *
+ * Contents: Routines implementing NTRUEncrypt encryption and decryption and
+ * key generation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto.h"
+#include "ntru_crypto_ntru_encrypt_param_sets.h"
+#include "ntru_crypto_ntru_encrypt_key.h"
+#include "ntru_crypto_ntru_convert.h"
+#include "ntru_crypto_ntru_poly.h"
+#include "ntru_crypto_ntru_mgf1.h"
+#include "ntru_crypto_drbg.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 DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than ct) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ * (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
+ * maximum plaintext length for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ * invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
+ * is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ * allocated from the heap.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt(
+ DRBG_HANDLE drbg_handle, /* 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_ENCRYPT_PARAM_SET *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 = 0;
+ uint16_t *scratch_buf = NULL;
+ uint16_t *ringel_buf = NULL;
+ uint16_t *r_buf = NULL;
+ uint8_t *b_buf = NULL;
+ uint8_t *tmp_buf = NULL;
+ bool msg_rep_good = FALSE;
+ NTRU_CRYPTO_HASH_ALGID hash_algid;
+ uint8_t md_len;
+ uint16_t mprime_len = 0;
+ uint16_t mod_q_mask;
+ uint32_t result = NTRU_OK;
+
+ /* check for bad parameters */
+
+ if (!pubkey_blob || !pt || !ct_len)
+ NTRU_RET(NTRU_BAD_PARAMETER);
+ if ((pubkey_blob_len == 0) || (pt_len == 0))
+ NTRU_RET(NTRU_BAD_LENGTH);
+
+ /* 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))
+ NTRU_RET(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;
+ NTRU_RET(NTRU_OK);
+ }
+
+ /* check the ciphertext buffer size */
+
+ if (*ct_len < packed_ct_len) {
+ NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+ }
+
+ /* check the plaintext length */
+
+ if (pt_len > params->m_len_max) {
+ NTRU_RET(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) {
+ NTRU_RET(NTRU_OUT_OF_MEMORY);
+ }
+ ringel_buf = scratch_buf + ring_mult_tmp_len;
+ r_buf = ringel_buf + params->N;
+ b_buf = (uint8_t *)(r_buf + (dr << 1));
+ tmp_buf = (uint8_t *)scratch_buf;
+
+ /* set hash algorithm based on security strength */
+
+ if (params->sec_strength_len <= 20) {
+ hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
+ md_len = 20;
+ } else {
+ hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
+ md_len = 32;
+ }
+
+ /* 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 */
+ result = ntru_crypto_drbg_generate(drbg_handle,
+ params->sec_strength_len << 3,
+ params->sec_strength_len, b_buf);
+
+ 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;
+
+
+ /* generate r */
+
+ result = ntru_gen_poly(hash_algid, md_len,
+ params->min_IGF_hash_calls,
+ (uint16_t)(ptr - tmp_buf),
+ tmp_buf, tmp_buf,
+ params->N, params->c_bits,
+ params->no_bias_limit,
+ params->is_product_form,
+ params->dF_r << 1, r_buf);
+ }
+
+ if (result == NTRU_OK) {
+ uint16_t pubkey_packed_len;
+
+ /* unpack the public key */
+
+ assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
+ pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
+ ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
+ params->q_bits, ringel_buf);
+
+ /* form R = h * r */
+
+ if (params->is_product_form)
+ ntru_ring_mult_product_indices(ringel_buf, (uint16_t)dr1,
+ (uint16_t)dr2, (uint16_t)dr3,
+ r_buf, params->N, params->q,
+ scratch_buf, ringel_buf);
+ else
+ ntru_ring_mult_indices(ringel_buf, (uint16_t)dr, (uint16_t)dr,
+ r_buf, params->N, params->q,
+ scratch_buf, ringel_buf);
+
+ /* form R mod 4 */
+
+ ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf);
+
+ /* form mask */
+
+ result = ntru_mgftp1(hash_algid, md_len,
+ params->min_MGF_hash_calls,
+ (params->N + 3) / 4, tmp_buf,
+ tmp_buf + params->N, params->N, tmp_buf);
+ }
+ 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);
+
+ /* form the msg representative m' by adding Mtrin to mask, mod p */
+
+ if (params->is_product_form) {
+ for (i = 0; i < mprime_len; i++) {
+ tmp_buf[i] = tmp_buf[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] = tmp_buf[i] + Mtrin_buf[i];
+ if (tmp_buf[i] >= 3)
+ tmp_buf[i] -= 3;
+ }
+ }
+
+ /* 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);
+ msg_rep_good = TRUE;
+ }
+ } 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;
+}
+
+
+/* ntru_crypto_ntru_decrypt
+ *
+ * Implements NTRU decryption (SVES) for the parameter set specified in
+ * the private key blob.
+ *
+ * The maximum size of the output plaintext may be queried by invoking
+ * this function with pt = NULL. In this case, no decryption is performed,
+ * NTRU_OK is returned, and the maximum size the plaintext could be is
+ * returned in pt_len.
+ * Note that until the decryption is performed successfully, the actual size
+ * of the resulting plaintext cannot be known.
+ *
+ * When pt != NULL, at invocation *pt_len must be the size of the pt buffer.
+ * Upon return it is the actual size of the plaintext.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than pt) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ * (privkey_blob) is zero, or if ct_len is invalid for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
+ * invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
+ * is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ * allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
+ */
+
+uint32_t
+ntru_crypto_ntru_decrypt(
+ uint16_t privkey_blob_len, /* in - no. of octets in private key
+ blob */
+ uint8_t const *privkey_blob, /* in - pointer to private key */
+ uint16_t ct_len, /* in - no. of octets in ciphertext */
+ uint8_t const *ct, /* in - pointer to ciphertext */
+ uint16_t *pt_len, /* in/out - no. of octets in pt, addr for
+ no. of octets in plaintext */
+ uint8_t *pt) /* out - address for plaintext */
+{
+ NTRU_ENCRYPT_PARAM_SET *params = NULL;
+ uint8_t const *privkey_packed = NULL;
+ uint8_t const *pubkey_packed = NULL;
+ uint8_t privkey_pack_type = 0x00;
+ uint8_t pubkey_pack_type = 0x00;
+ size_t scratch_buf_len;
+ uint32_t dF_r;
+ uint32_t dF_r1 = 0;
+ uint32_t dF_r2 = 0;
+ uint32_t dF_r3 = 0;
+ uint16_t ring_mult_tmp_len;
+ int16_t m1 = 0;
+ uint16_t *scratch_buf = NULL;
+ uint16_t *ringel_buf1 = NULL;
+ uint16_t *ringel_buf2 = NULL;
+ uint16_t *i_buf = NULL;
+ uint8_t *m_buf = NULL;
+ uint8_t *tmp_buf = NULL;
+ uint8_t *Mtrin_buf = NULL;
+ uint8_t *M_buf = NULL;
+ uint8_t *ptr = NULL;
+ NTRU_CRYPTO_HASH_ALGID hash_algid;
+ uint8_t md_len;
+ uint16_t cmprime_len;
+ uint16_t mod_q_mask;
+ uint16_t q_mod_p;
+ uint16_t cm_len = 0;
+ uint16_t num_zeros;
+ uint16_t i;
+ bool decryption_ok = TRUE;
+ uint32_t result = NTRU_OK;
+
+ /* check for bad parameters */
+
+ if (!privkey_blob || !ct || !pt_len)
+ NTRU_RET(NTRU_BAD_PARAMETER);
+ if ((privkey_blob_len == 0) || (ct_len == 0))
+ NTRU_RET(NTRU_BAD_LENGTH);
+
+ /* get a pointer to the parameter-set parameters, the packing types for
+ * the public and private keys, and pointers to the packed public and
+ * private keys
+ */
+
+ if (!ntru_crypto_ntru_encrypt_key_parse(FALSE /* privkey */,
+ privkey_blob_len,
+ privkey_blob, &pubkey_pack_type,
+ &privkey_pack_type, ¶ms,
+ &pubkey_packed, &privkey_packed))
+ NTRU_RET(NTRU_BAD_PRIVATE_KEY);
+
+ /* return the max plaintext size if requested */
+
+ if (!pt) {
+ *pt_len = params->m_len_max;
+ NTRU_RET(NTRU_OK);
+ }
+
+ /* cannot check the plaintext buffer size until after the plaintext
+ * is derived, if we allow plaintext buffers only as large as the
+ * actual plaintext
+ */
+
+ /* check the ciphertext length */
+
+ if (ct_len != (params->N * params->q_bits + 7) >> 3)
+ NTRU_RET(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 */
+ dF_r1 = params->dF_r & 0xff;
+ dF_r2 = (params->dF_r >> 8) & 0xff;
+ dF_r3 = (params->dF_r >> 16) & 0xff;
+ dF_r = dF_r1 + dF_r2 + dF_r3;
+ } else {
+ ring_mult_tmp_len = params->N; /* N 16-bit word buffer */
+ dF_r = params->dF_r;
+ }
+ scratch_buf_len = (ring_mult_tmp_len << 1) +
+ /* X-byte temp buf for ring mult and
+ other intermediate results */
+ (params->N << 2) + /* 2 2N-byte bufs for ring elements
+ and overflow from temp buffer */
+ (dF_r << 2) + /* buffer for F, r indices */
+ params->m_len_max; /* buffer for plaintext */
+ scratch_buf = malloc(scratch_buf_len);
+ if (!scratch_buf) {
+ NTRU_RET(NTRU_OUT_OF_MEMORY);
+ }
+ ringel_buf1 = scratch_buf + ring_mult_tmp_len;
+ ringel_buf2 = ringel_buf1 + params->N;
+ i_buf = ringel_buf2 + params->N;
+ m_buf = (uint8_t *)(i_buf + (dF_r << 1));
+ tmp_buf = (uint8_t *)scratch_buf;
+ Mtrin_buf = (uint8_t *)ringel_buf1;
+ M_buf = Mtrin_buf + params->N;
+
+ /* set hash algorithm based on security strength */
+
+ if (params->sec_strength_len <= 20) {
+ hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
+ md_len = 20;
+ } else {
+ hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
+ md_len = 32;
+ }
+
+ /* set constants */
+
+ mod_q_mask = params->q - 1;
+ q_mod_p = params->q % 3;
+
+ /* unpack the ciphertext */
+
+ ntru_octets_2_elements(ct_len, ct, params->q_bits, ringel_buf2);
+
+ /* unpack the private key */
+
+ if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) {
+ ntru_packed_trits_2_indices(privkey_packed, params->N, i_buf,
+ i_buf + dF_r);
+
+ } else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES) {
+ ntru_octets_2_elements(
+ (((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3,
+ privkey_packed, params->N_bits, i_buf);
+
+ } else {
+ assert(FALSE);
+ }
+
+ /* form cm':
+ * F * e
+ * A = e * (1 + pF) mod q = e + pFe mod q
+ * a = A in the range [-q/2, q/2)
+ * cm' = a mod p
+ */
+
+ cmprime_len = params->N;
+ if (params->is_product_form) {
+ --cmprime_len;
+ ntru_ring_mult_product_indices(ringel_buf2, (uint16_t)dF_r1,
+ (uint16_t)dF_r2, (uint16_t)dF_r3,
+ i_buf, params->N, params->q,
+ scratch_buf, ringel_buf1);
+ for (i = 0; i < cmprime_len; i++) {
+ ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask;
+ if (ringel_buf1[i] >= (params->q >> 1))
+ ringel_buf1[i] = ringel_buf1[i] - q_mod_p;
+ Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3);
+ if (Mtrin_buf[i] == 1)
+ ++m1;
+ else if (Mtrin_buf[i] == 2)
+ --m1;
+ }
+ } else {
+ ntru_ring_mult_indices(ringel_buf2, (uint16_t)dF_r, (uint16_t)dF_r,
+ i_buf, params->N, params->q,
+ scratch_buf, ringel_buf1);
+ for (i = 0; i < cmprime_len; i++) {
+ ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask;
+ if (ringel_buf1[i] >= (params->q >> 1))
+ ringel_buf1[i] = ringel_buf1[i] - q_mod_p;
+ Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3);
+ }
+ }
+
+ /* check that the candidate message representative meets minimum weight
+ * requirements
+ */
+
+ if (params->is_product_form)
+ decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) :
+ (bool)( m1 <= params->min_msg_rep_wt);
+ else
+ decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf,
+ params->min_msg_rep_wt);
+
+ /* form cR = e - cm' mod q */
+
+ for (i = 0; i < cmprime_len; i++) {
+ if (Mtrin_buf[i] == 1)
+ ringel_buf2[i] = --ringel_buf2[i] & mod_q_mask;
+ else if (Mtrin_buf[i] == 2)
+ ringel_buf2[i] = ++ringel_buf2[i] & mod_q_mask;
+ }
+ if (params->is_product_form)
+ ringel_buf2[i] = (ringel_buf2[i] + m1) & mod_q_mask;
+
+
+ /* form cR mod 4 */
+
+ ntru_coeffs_mod4_2_octets(params->N, ringel_buf2, tmp_buf);
+
+ /* form mask */
+
+ result = ntru_mgftp1(hash_algid, md_len,
+ params->min_MGF_hash_calls,
+ (params->N + 3) / 4, tmp_buf,
+ tmp_buf + params->N, params->N, tmp_buf);
+
+ if (result == NTRU_OK) {
+
+ /* form cMtrin by subtracting mask from cm', mod p */
+
+ for (i = 0; i < cmprime_len; i++) {
+ Mtrin_buf[i] = Mtrin_buf[i] - tmp_buf[i];
+ if (Mtrin_buf[i] >= 3)
+ Mtrin_buf[i] += 3;
+ }
+ if (params->is_product_form)
+
+ /* set the last trit to zero since that's what it was, and
+ * because it can't be calculated from (cm' - mask) since
+ * we don't have the correct value for the last cm' trit
+ */
+
+ Mtrin_buf[i] = 0;
+
+ /* convert cMtrin to cM (Mtrin to Mbin) */
+
+ if (!ntru_trits_2_bits(Mtrin_buf, params->N, M_buf))
+ decryption_ok = FALSE;
+
+ /* validate the padded message cM and copy cm to m_buf */
+
+ ptr = M_buf + params->sec_strength_len;
+ if (params->m_len_len == 2)
+ cm_len = (uint16_t)(*ptr++) << 16;
+ cm_len |= (uint16_t)(*ptr++);
+ if (cm_len > params->m_len_max) {
+ cm_len = params->m_len_max;
+ decryption_ok = FALSE;
+ }
+ memcpy(m_buf, ptr, cm_len);
+ ptr += cm_len;
+ num_zeros = params->m_len_max - cm_len + 1;
+ for (i = 0; i < num_zeros; i++) {
+ if (ptr[i] != 0)
+ decryption_ok = FALSE;
+ }
+
+ /* form sData (OID || m || b || hTrunc) */
+
+ ptr = tmp_buf;
+ memcpy(ptr, params->OID, 3);
+ ptr += 3;
+ memcpy(ptr, m_buf, cm_len);
+ ptr += cm_len;
+ memcpy(ptr, M_buf, params->sec_strength_len);
+ ptr += params->sec_strength_len;
+ memcpy(ptr, pubkey_packed, params->sec_strength_len);
+ ptr += params->sec_strength_len;
+
+ /* generate cr */
+
+ result = ntru_gen_poly(hash_algid, md_len,
+ params->min_IGF_hash_calls,
+ (uint16_t)(ptr - tmp_buf),
+ tmp_buf, tmp_buf,
+ params->N, params->c_bits,
+ params->no_bias_limit,
+ params->is_product_form,
+ params->dF_r << 1, i_buf);
+ }
+
+ if (result == NTRU_OK) {
+
+ /* unpack the public key */
+
+ {
+ uint16_t pubkey_packed_len;
+
+ assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
+ pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
+ ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
+ params->q_bits, ringel_buf1);
+ }
+
+ /* form cR' = h * cr */
+
+ if (params->is_product_form)
+ ntru_ring_mult_product_indices(ringel_buf1, (uint16_t)dF_r1,
+ (uint16_t)dF_r2, (uint16_t)dF_r3,
+ i_buf, params->N, params->q,
+ scratch_buf, ringel_buf1);
+ else
+ ntru_ring_mult_indices(ringel_buf1, (uint16_t)dF_r, (uint16_t)dF_r,
+ i_buf, params->N, params->q,
+ scratch_buf, ringel_buf1);
+
+ /* compare cR' to cR */
+
+ for (i = 0; i < params->N; i++) {
+ if (ringel_buf1[i] != ringel_buf2[i])
+ decryption_ok = FALSE;
+ }
+
+ /* output plaintext and plaintext length */
+
+ if (decryption_ok) {
+ if (*pt_len < cm_len)
+ NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+ memcpy(pt, m_buf, cm_len);
+ *pt_len = cm_len;
+ }
+ }
+
+ /* cleanup */
+
+ memset(scratch_buf, 0, scratch_buf_len);
+ free(scratch_buf);
+
+ if (!decryption_ok)
+ NTRU_RET(NTRU_FAIL);
+ return result;
+}
+
+
+/* ntru_crypto_ntru_encrypt_keygen
+ *
+ * Implements key generation for NTRUEncrypt for the parameter set specified.
+ *
+ * Before invoking this function, a DRBG must be instantiated using
+ * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
+ * instantiation the requested security strength must be at least as large
+ * as the security strength of the NTRU parameter set being used.
+ * Failure to instantiate the DRBG with the proper security strength will
+ * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * The required minimum size of the output private-key buffer (privkey_blob)
+ * may be queried by invoking this function with privkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for privkey_blob is returned in privkey_blob_len.
+ *
+ * The required minimum sizes of both pubkey_blob and privkey_blob may be
+ * queried as described above, in a single invocation of this function.
+ *
+ * When pubkey_blob != NULL and privkey_blob != NULL, at invocation
+ * *pubkey_blob_len must be the size of the pubkey_blob buffer and
+ * *privkey_blob_len must be the size of the privkey_blob buffer.
+ * Upon return, *pubkey_blob_len is the actual size of the public-key blob
+ * and *privkey_blob_len is the actual size of the private-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than pubkey_blob or privkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
+ * ID is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
+ * buffer or the privkey_blob buffer is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ * allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
+ * not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
+ * Should this occur, this function should simply be invoked again.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt_keygen(
+ DRBG_HANDLE drbg_handle, /* in - handle of DRBG */
+ NTRU_ENCRYPT_PARAM_SET_ID param_set_id, /* in - parameter set ID */
+ uint16_t *pubkey_blob_len, /* in/out - no. of octets in
+ pubkey_blob, addr
+ for no. of octets
+ in pubkey_blob */
+ uint8_t *pubkey_blob, /* out - address for
+ public key blob */
+ uint16_t *privkey_blob_len, /* in/out - no. of octets in
+ privkey_blob, addr
+ for no. of octets
+ in privkey_blob */
+ uint8_t *privkey_blob) /* out - address for
+ private key blob */
+{
+ NTRU_ENCRYPT_PARAM_SET *params = NULL;
+ uint16_t public_key_blob_len;
+ uint16_t private_key_blob_len;
+ uint8_t pubkey_pack_type;
+ uint8_t privkey_pack_type;
+ size_t scratch_buf_len;
+ uint32_t dF;
+ uint32_t dF1 = 0;
+ uint32_t dF2 = 0;
+ uint32_t dF3 = 0;
+ uint16_t *scratch_buf = NULL;
+ uint16_t *ringel_buf1 = NULL;
+ uint16_t *ringel_buf2 = NULL;
+ uint16_t *F_buf = NULL;
+ uint8_t *tmp_buf = NULL;
+ uint16_t mod_q_mask;
+ NTRU_CRYPTO_HASH_ALGID hash_algid;
+ uint8_t md_len;
+ uint16_t seed_len;
+ uint32_t result = NTRU_OK;
+
+ /* get a pointer to the parameter-set parameters */
+
+ if ((params = ntru_encrypt_get_params_with_id(param_set_id)) == NULL)
+ NTRU_RET(NTRU_INVALID_PARAMETER_SET);
+
+ /* check for bad parameters */
+
+ if (!pubkey_blob_len || !privkey_blob_len)
+ NTRU_RET(NTRU_BAD_PARAMETER);
+
+ /* get public and private key packing types and blob lengths */
+
+ ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type,
+ &public_key_blob_len,
+ &privkey_pack_type,
+ &private_key_blob_len);
+
+ /* return the pubkey_blob size and/or privkey_blob size if requested */
+
+ if (!pubkey_blob || !privkey_blob) {
+ if (!pubkey_blob)
+ *pubkey_blob_len = public_key_blob_len;
+ if (!privkey_blob)
+ *privkey_blob_len = private_key_blob_len;
+ NTRU_RET(NTRU_OK);
+ }
+
+ /* check size of output buffers */
+
+ if ((*pubkey_blob_len < public_key_blob_len) ||
+ (*privkey_blob_len < private_key_blob_len))
+ NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+
+ /* allocate memory for all operations */
+
+ if (params->is_product_form) {
+ dF1 = params->dF_r & 0xff;
+ dF2 = (params->dF_r >> 8) & 0xff;
+ dF3 = (params->dF_r >> 16) & 0xff;
+ dF = dF1 + dF2 + dF3;
+ } else {
+ dF = params->dF_r;
+ }
+
+ scratch_buf_len = (params->N * 8) + /* 4N-byte temp buffer for ring inv
+ and other intermediate results,
+ 2N-byte buffer for f, g indices
+ and overflow from temp buffer,
+ 2N-byte buffer for f^-1 */
+ (dF << 2); /* buffer for F indices */
+ scratch_buf = malloc(scratch_buf_len);
+ if (!scratch_buf) {
+ NTRU_RET(NTRU_OUT_OF_MEMORY);
+ }
+ ringel_buf1 = scratch_buf + (params->N << 1);
+ ringel_buf2 = ringel_buf1 + params->N;
+ F_buf = ringel_buf2 + params->N;
+ tmp_buf = (uint8_t *)scratch_buf;
+
+ /* set hash algorithm and seed length based on security strength */
+
+ if (params->sec_strength_len <= 20) {
+ hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
+ md_len = 20;
+ } else {
+ hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
+ md_len = 32;
+ }
+ seed_len = params->sec_strength_len + 8;
+
+ /* set constants */
+
+ mod_q_mask = params->q - 1;
+
+ /* get random bytes for seed for generating trinary F
+ * as a list of indices
+ */
+
+ result = ntru_crypto_drbg_generate(drbg_handle,
+ params->sec_strength_len << 3,
+ seed_len, tmp_buf);
+
+ if (result == NTRU_OK) {
+
+ /* generate F */
+
+ result = ntru_gen_poly(hash_algid, md_len,
+ params->min_IGF_hash_calls,
+ seed_len, tmp_buf, tmp_buf,
+ params->N, params->c_bits,
+ params->no_bias_limit,
+ params->is_product_form,
+ params->dF_r << 1, F_buf);
+ }
+
+ if (result == NTRU_OK) {
+ uint32_t i;
+
+ memset(ringel_buf1, 0, params->N * sizeof(uint16_t));
+
+ /* form F as a ring element */
+
+ if (params->is_product_form) {
+ uint32_t dF3_offset = (dF1 + dF2) << 1;
+
+ /* form F1 as a ring element */
+
+ for (i = 0; i < dF1; i++)
+ ringel_buf1[F_buf[i]] = 1;
+ for (; i < (dF1 << 1); i++)
+ ringel_buf1[F_buf[i]] = mod_q_mask;
+
+ /* form F1 * F2 */
+
+ ntru_ring_mult_indices(ringel_buf1, (uint16_t)dF2, (uint16_t)dF2,
+ F_buf + (dF1 << 1), params->N, params->q,
+ scratch_buf, ringel_buf1);
+
+ /* form (F1 * F2) + F3 */
+
+ for (i = 0; i < dF3; i++) {
+ uint16_t index = F_buf[dF3_offset + i];
+ ringel_buf1[index] = ++ringel_buf1[index] & mod_q_mask;
+ }
+ for (; i < (dF3 << 1); i++) {
+ uint16_t index = F_buf[dF3_offset + i];
+ ringel_buf1[index] = --ringel_buf1[index] & mod_q_mask;
+ }
+
+ } else {
+
+ /* form F as a ring element */
+
+ for (i = 0; i < dF; i++)
+ ringel_buf1[F_buf[i]] = 1;
+ for (; i < (dF << 1); i++)
+ ringel_buf1[F_buf[i]] = mod_q_mask;
+ }
+
+ /* form f = 1 + pF */
+
+ for (i = 0; i < params->N; i++)
+ ringel_buf1[i] = (ringel_buf1[i] * 3) & mod_q_mask;
+ ringel_buf1[0] = (ringel_buf1[0] + 1) & mod_q_mask;
+
+ /* find f^-1 in (Z/qZ)[X]/(X^N - 1) */
+
+ if (!ntru_ring_inv(ringel_buf1, params->N, params->q,
+ scratch_buf, ringel_buf2))
+ result = NTRU_ERROR_BASE + NTRU_FAIL;
+ }
+
+ if (result == NTRU_OK) {
+
+ /* get random bytes for seed for generating trinary g
+ * as a list of indices
+ */
+ result = ntru_crypto_drbg_generate(drbg_handle,
+ params->sec_strength_len << 3,
+ seed_len, tmp_buf);
+ }
+
+ if (result == NTRU_OK) {
+ uint16_t min_IGF_hash_calls =
+ ((((params->dg << 2) + 2) * params->N_bits) + (md_len << 3) - 1) /
+ (md_len << 3);
+
+ /* generate g */
+
+ result = ntru_gen_poly(hash_algid, md_len,
+ (uint8_t)min_IGF_hash_calls,
+ seed_len, tmp_buf, tmp_buf,
+ params->N, params->c_bits,
+ params->no_bias_limit, FALSE,
+ (params->dg << 1) + 1, ringel_buf1);
+ }
+
+ if (result == NTRU_OK) {
+ uint16_t i;
+
+ /* compute h = p * (f^-1 * g) mod q */
+
+ ntru_ring_mult_indices(ringel_buf2, params->dg + 1, params->dg,
+ ringel_buf1, params->N, params->q, scratch_buf,
+ ringel_buf2);
+
+ for (i = 0; i < params->N; i++)
+ ringel_buf2[i] = (ringel_buf2[i] * 3) & mod_q_mask;
+
+ /* create public key blob */
+
+ ntru_crypto_ntru_encrypt_key_create_pubkey_blob(params, ringel_buf2,
+ pubkey_pack_type,
+ pubkey_blob);
+ *pubkey_blob_len = public_key_blob_len;
+
+ /* create private key blob */
+
+ ntru_crypto_ntru_encrypt_key_create_privkey_blob(params, ringel_buf2,
+ F_buf,
+ privkey_pack_type,
+ tmp_buf, privkey_blob);
+ *privkey_blob_len = private_key_blob_len;
+ }
+
+ /* cleanup */
+
+ memset(scratch_buf, 0, scratch_buf_len);
+ free(scratch_buf);
+
+ return result;
+}
+
+
+/* DER-encoding prefix template for NTRU public keys,
+ * with parameter-set-specific fields nomalized
+ */
+
+static uint8_t const der_prefix_template[] = {
+ 0x30, 0x82,
+ 0x00, 0x23, /* add pubkey length */
+ 0x30, 0x18, 0x06, 0x0a, 0x2b, 0x06, 0x01,
+ 0x04, 0x01, 0xc1, 0x70, 0x01, 0x01, 0x02, /* end of NTRU OID compare */
+ 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
+ 0xc1, 0x70, 0x01, 0x02,
+ 0x00, /* set param-set DER id */
+ 0x03, 0x82,
+ 0x00, 0x05, /* add pubkey length */
+ 0x00, 0x04, 0x82,
+ 0x00, 0x00, /* add pubkey length */
+};
+
+
+/* add_16_to_8s
+ *
+ * adds a 16-bit value to two bytes
+ */
+
+static void
+add_16_to_8s(
+ uint16_t a,
+ uint8_t *b)
+{
+ uint16_t tmp = ((uint16_t)b[0] << 8) + b[1];
+
+ tmp = tmp + a;
+ b[0] = (uint8_t)((tmp >> 8) & 0xff);
+ b[1] = (uint8_t)(tmp & 0xff);
+}
+
+
+/* sub_16_from_8s
+ *
+ * subtracts a 16-bit value from two bytes
+ */
+
+static void
+sub_16_from_8s(
+ uint16_t a,
+ uint8_t *b)
+{
+ uint16_t tmp = ((uint16_t)b[0] << 8) + b[1];
+
+ tmp = tmp - a;
+ b[0] = (uint8_t)((tmp >> 8) & 0xff);
+ b[1] = (uint8_t)(tmp & 0xff);
+}
+
+
+/* ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo
+ *
+ * DER-encodes an NTRUEncrypt public-key from a public-key blob into a
+ * SubjectPublicKeyInfo field for inclusion in an X.509 certificate.
+ *
+ * The required minimum size of the output SubjectPublicKeyInfo buffer
+ * (encoded_subjectPublicKeyInfo) may be queried by invoking this function
+ * with encoded_subjectPublicKeyInfo = NULL. In this case, no encoding is
+ * performed, NTRU_OK is returned, and the required minimum size for
+ * encoded_subjectPublicKeyInfo is returned in encoded_subjectPublicKeyInfo_len.
+ *
+ * When encoded_subjectPublicKeyInfo != NULL, at invocation
+ * *encoded_subjectPublicKeyInfo_len must be the size of the
+ * encoded_subjectPublicKeyInfo buffer.
+ * Upon return, it is the actual size of the encoded public key.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than encoded_subjectPublicKeyInfo) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if pubkey_blob_len is zero.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ * invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the SubjectPublicKeyInfo
+ * buffer is too small.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+ uint16_t pubkey_blob_len, /* in - no. of octets in public-key
+ blob */
+ uint8_t const *pubkey_blob, /* in - ptr to public-key blob */
+ uint16_t *encoded_subjectPublicKeyInfo_len,
+ /* in/out - no. of octets in encoded info,
+ address for no. of octets in
+ encoded info */
+ uint8_t *encoded_subjectPublicKeyInfo)
+ /* out - address for encoded info */
+{
+ NTRU_ENCRYPT_PARAM_SET *params = NULL;
+ uint8_t const *pubkey_packed = NULL;
+ uint8_t pubkey_pack_type;
+ uint16_t packed_pubkey_len;
+ uint16_t encoded_len;
+
+ /* check for bad parameters */
+
+ if (!pubkey_blob || !encoded_subjectPublicKeyInfo_len)
+ NTRU_RET(NTRU_BAD_PARAMETER);
+ if (pubkey_blob_len == 0)
+ NTRU_RET(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))
+ NTRU_RET(NTRU_BAD_PUBLIC_KEY);
+
+ /* return the encoded_subjectPublicKeyInfo size if requested */
+
+ packed_pubkey_len = (params->N * params->q_bits + 7) >> 3;
+ encoded_len = sizeof(der_prefix_template) + packed_pubkey_len;
+ if (!encoded_subjectPublicKeyInfo) {
+ *encoded_subjectPublicKeyInfo_len = encoded_len;
+ NTRU_RET(NTRU_OK);
+ }
+
+ /* check the encoded_subjectPublicKeyInfo buffer size */
+
+ if (*encoded_subjectPublicKeyInfo_len < encoded_len) {
+ NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+ }
+
+ /* form the encoded subjectPublicKey */
+
+ memcpy(encoded_subjectPublicKeyInfo, der_prefix_template,
+ sizeof(der_prefix_template));
+ add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 2);
+ add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 32);
+ add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 37);
+ encoded_subjectPublicKeyInfo[29] = params->der_id;
+ memcpy(encoded_subjectPublicKeyInfo + sizeof(der_prefix_template),
+ pubkey_packed, packed_pubkey_len);
+
+ *encoded_subjectPublicKeyInfo_len = encoded_len;
+
+ NTRU_RET(NTRU_OK);
+}
+
+
+/* ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey
+ *
+ * Decodes a DER-encoded NTRUEncrypt public-key from a
+ * SubjectPublicKeyInfo field in an X.509 certificate and returns the
+ * public-key blob itself.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no decoding is performed, NTRU_OK is returned, and the
+ * required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * When pubkey_blob != NULL, at invocation *pubkey_blob_len must be the
+ * size of the pubkey_blob buffer.
+ * Upon return, it is the actual size of the public-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ * (other than pubkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_ENCODING if the encoded data is
+ * an invalid encoding of an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_OID_NOT_RECOGNIZED if the
+ * encoded data contains an OID that identifies an object other than
+ * an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the pubkey_blob buffer
+ * is too small.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(
+ uint8_t const *encoded_data, /* in - ptr to subjectPublicKeyInfo
+ in the encoded data */
+ uint16_t *pubkey_blob_len, /* in/out - no. of octets in pubkey blob,
+ address for no. of octets in
+ pubkey blob */
+ uint8_t *pubkey_blob, /* out - address for pubkey blob */
+ uint8_t **next) /* out - address for ptr to encoded
+ data following the
+ subjectPublicKeyInfo */
+{
+ NTRU_ENCRYPT_PARAM_SET *params = NULL;
+ uint8_t prefix_buf[39];
+ bool der_id_valid;
+ uint16_t packed_pubkey_len = 0;
+ uint8_t pubkey_pack_type;
+ uint16_t public_key_blob_len;
+
+ /* check for bad parameters */
+
+ if (!encoded_data || !pubkey_blob_len || !next)
+ NTRU_RET(NTRU_BAD_PARAMETER);
+
+ /* determine if data to be decoded is a valid encoding of an NTRU
+ * public key
+ */
+
+ memcpy(prefix_buf, encoded_data, sizeof(prefix_buf));
+
+ /* get a pointer to the parameter-set parameters */
+
+ if ((params = ntru_encrypt_get_params_with_DER_id(encoded_data[29])) ==
+ NULL) {
+ der_id_valid = FALSE;
+
+ /* normalize the prefix-buffer data used in an NTRU OID comparison */
+
+ prefix_buf[2] = der_prefix_template[2];
+ prefix_buf[3] = der_prefix_template[3];
+
+ } else {
+ der_id_valid = TRUE;
+
+ /* normalize the prefix-buffer data for the specific parameter set */
+
+ packed_pubkey_len = (params->N * params->q_bits + 7) >> 3;
+ sub_16_from_8s(packed_pubkey_len, prefix_buf + 2);
+ sub_16_from_8s(packed_pubkey_len, prefix_buf + 32);
+ sub_16_from_8s(packed_pubkey_len, prefix_buf + 37);
+ prefix_buf[29] = 0;
+ }
+
+ /* validate the DER prefix encoding */
+
+ if (!der_id_valid || memcmp(prefix_buf, der_prefix_template,
+ sizeof(der_prefix_template))) {
+
+ /* bad DER prefix, so determine if this is a bad NTRU encoding or an
+ * unknown OID by comparing the first 18 octets
+ */
+
+ if (memcmp(prefix_buf, der_prefix_template, 18))
+ NTRU_RET(NTRU_OID_NOT_RECOGNIZED);
+ else
+ NTRU_RET(NTRU_BAD_ENCODING);
+ }
+
+ /* get public key packing type and blob length */
+
+ ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type,
+ &public_key_blob_len, NULL,
+ NULL);
+
+ /* return the pubkey_blob size if requested */
+
+ if (!pubkey_blob) {
+ *pubkey_blob_len = public_key_blob_len;
+ NTRU_RET(NTRU_OK);
+ }
+
+ /* check size of output buffer */
+
+ if (*pubkey_blob_len < public_key_blob_len)
+ NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+
+ /* create the public-key blob */
+
+ ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(params, packed_pubkey_len,
+ encoded_data + sizeof(der_prefix_template),
+ pubkey_pack_type, pubkey_blob);
+ *pubkey_blob_len = public_key_blob_len;
+
+ *next = *next + sizeof(der_prefix_template) + packed_pubkey_len;
+
+ NTRU_RET(NTRU_OK);
+}
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_encrypt_key.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013 Security Innovation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_encrypt_key.c
+ *
+ * Contents: Routines for exporting and importing public and private keys
+ * for NTRUEncrypt.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_encrypt_key.h"
+
+
+/* ntru_crypto_ntru_encrypt_key_parse
+ *
+ * Parses an NTRUEncrypt key blob.
+ * If the blob is not corrupt, returns packing types for public and private
+ * keys, a pointer to the parameter set, a pointer to the public key, and
+ * a pointer to the private key if it exists.
+ *
+ * Returns TRUE if successful.
+ * Returns FALSE if the blob is invalid.
+ */
+
+bool
+ntru_crypto_ntru_encrypt_key_parse(
+ bool pubkey_parse, /* in - if parsing pubkey
+ blob */
+ uint16_t key_blob_len, /* in - no. octets in key
+ blob */
+ uint8_t const *key_blob, /* in - pointer to key blob */
+ uint8_t *pubkey_pack_type, /* out - addr for pubkey
+ packing type */
+ uint8_t *privkey_pack_type, /* out - addr for privkey
+ packing type */
+ NTRU_ENCRYPT_PARAM_SET **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;
+
+ assert(key_blob_len);
+ assert(key_blob);
+ assert(pubkey_pack_type);
+ assert(params);
+ assert(pubkey);
+
+ /* parse key blob based on tag */
+
+ tag = key_blob[0];
+ switch (tag) {
+ case NTRU_ENCRYPT_PUBKEY_TAG:
+ if (!pubkey_parse)
+ return FALSE;
+ break;
+ case NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG:
+ case NTRU_ENCRYPT_PRIVKEY_TRITS_TAG:
+ case NTRU_ENCRYPT_PRIVKEY_INDICES_TAG:
+ assert(privkey_pack_type);
+ assert(privkey);
+ if (pubkey_parse)
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+
+ switch (tag) {
+ case NTRU_ENCRYPT_PUBKEY_TAG:
+ case NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG:
+ case NTRU_ENCRYPT_PRIVKEY_TRITS_TAG:
+ case NTRU_ENCRYPT_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_ENCRYPT_PARAM_SET *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 */
+
+ if ((p = ntru_encrypt_get_params_with_OID(key_blob + 2)) == NULL)
+ 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_ENCRYPT_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_ENCRYPT_PRIVKEY_DEFAULT_TAG) {
+ if (p->is_product_form ||
+ (privkey_packed_indices_len <=
+ privkey_packed_trits_len))
+ tag = NTRU_ENCRYPT_PRIVKEY_INDICES_TAG;
+ else
+ tag = NTRU_ENCRYPT_PRIVKEY_TRITS_TAG;
+ }
+
+ if (tag == NTRU_ENCRYPT_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_ENCRYPT_PRIVKEY_TRITS_TAG) ?
+ NTRU_ENCRYPT_KEY_PACKED_TRITS :
+ NTRU_ENCRYPT_KEY_PACKED_INDICES;
+ }
+
+ /* return parameter set pointer */
+
+ *pubkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS;
+ *params = p;
+ }
+ default:
+ break; /* can't get here */
+ }
+ return TRUE;
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_get_blob_params
+ *
+ * Returns public and private key packing types and blob lengths given
+ * a packing format. For now, only a default packing format exists.
+ *
+ * Only public-key params may be returned by setting privkey_pack_type
+ * and privkey_blob_len to NULL.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_get_blob_params(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint8_t *pubkey_pack_type, /* out - addr for pubkey
+ packing type */
+ uint16_t *pubkey_blob_len, /* out - addr for no. of
+ bytes in
+ pubkey blob */
+ uint8_t *privkey_pack_type, /* out - addr for privkey
+ packing type */
+ uint16_t *privkey_blob_len) /* out - addr for no. of
+ bytes in
+ privkey blob */
+{
+ uint16_t pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
+
+ assert(params);
+ assert(pubkey_pack_type);
+ assert(pubkey_blob_len);
+
+ *pubkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS;
+ *pubkey_blob_len = 5 + pubkey_packed_len;
+
+ if (privkey_pack_type && privkey_blob_len) {
+ uint16_t privkey_packed_trits_len = (params->N + 4) / 5;
+ uint16_t privkey_packed_indices_len;
+ uint16_t dF;
+
+ 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 = ((dF << 1) * params->N_bits + 7) >> 3;
+
+ if (params->is_product_form ||
+ (privkey_packed_indices_len <= privkey_packed_trits_len)) {
+ *privkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_INDICES;
+ *privkey_blob_len =
+ 5 + pubkey_packed_len + privkey_packed_indices_len;
+ } else {
+ *privkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_TRITS;
+ *privkey_blob_len =
+ 5 + pubkey_packed_len + privkey_packed_trits_len;
+ }
+ }
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_create_pubkey_blob
+ *
+ * Returns a public key blob, packed according to the packing type provided.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_create_pubkey_blob(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint16_t const *pubkey, /* in - pointer to the
+ coefficients
+ of the pubkey */
+ uint8_t pubkey_pack_type, /* out - pubkey packing
+ type */
+ uint8_t *pubkey_blob) /* out - addr for the
+ pubkey blob */
+{
+ assert(params);
+ assert(pubkey);
+ assert(pubkey_blob);
+
+ switch (pubkey_pack_type) {
+ case NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS:
+ *pubkey_blob++ = NTRU_ENCRYPT_PUBKEY_TAG;
+ *pubkey_blob++ = (uint8_t)sizeof(params->OID);
+ memcpy(pubkey_blob, params->OID, sizeof(params->OID));
+ pubkey_blob += sizeof(params->OID);
+ ntru_elements_2_octets(params->N, pubkey, params->q_bits,
+ pubkey_blob);
+ break;
+ default:
+ assert(FALSE);
+ }
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob
+ *
+ * Returns a public key blob, recreated from an already-packed public key.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint16_t packed_pubkey_len, /* in - no. octets in
+ packed pubkey */
+ uint8_t const *packed_pubkey, /* in - pointer to the
+ packed pubkey */
+ uint8_t pubkey_pack_type, /* out - pubkey packing
+ type */
+ uint8_t *pubkey_blob) /* out - addr for the
+ pubkey blob */
+{
+ assert(params);
+ assert(packed_pubkey);
+ assert(pubkey_blob);
+
+ switch (pubkey_pack_type) {
+ case NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS:
+ *pubkey_blob++ = NTRU_ENCRYPT_PUBKEY_TAG;
+ *pubkey_blob++ = (uint8_t)sizeof(params->OID);
+ memcpy(pubkey_blob, params->OID, sizeof(params->OID));
+ pubkey_blob += sizeof(params->OID);
+ memcpy(pubkey_blob, packed_pubkey, packed_pubkey_len);
+ break;
+ default:
+ assert(FALSE);
+ }
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_create_privkey_blob
+ *
+ * Returns a private key blob, packed according to the packing type provided.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_create_privkey_blob(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint16_t const *pubkey, /* in - pointer to the
+ coefficients
+ of the pubkey */
+ uint16_t const *privkey, /* in - pointer to the
+ indices of the
+ privkey */
+ uint8_t privkey_pack_type, /* in - privkey packing
+ type */
+ uint8_t *buf, /* in - temp, N bytes */
+ uint8_t *privkey_blob) /* out - addr for the
+ privkey blob */
+{
+ assert(params);
+ assert(pubkey);
+ assert(privkey);
+ assert(privkey_blob);
+
+ switch (privkey_pack_type) {
+ case NTRU_ENCRYPT_KEY_PACKED_TRITS:
+ case NTRU_ENCRYPT_KEY_PACKED_INDICES:
+
+ /* format header and packed public key */
+
+ *privkey_blob++ = NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG;
+ *privkey_blob++ = (uint8_t)sizeof(params->OID);
+ memcpy(privkey_blob, params->OID, sizeof(params->OID));
+ privkey_blob += sizeof(params->OID);
+ ntru_elements_2_octets(params->N, pubkey, params->q_bits,
+ privkey_blob);
+ privkey_blob += (params->N * params->q_bits + 7) >> 3;
+
+ /* add packed private key */
+
+ if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) {
+ ntru_indices_2_packed_trits(privkey, (uint16_t)params->dF_r,
+ (uint16_t)params->dF_r,
+ params->N, buf, privkey_blob);
+ } else {
+ uint32_t dF;
+
+ if (params->is_product_form) {
+ dF = (params->dF_r & 0xff) +
+ ((params->dF_r >> 8) & 0xff) +
+ ((params->dF_r >> 16) & 0xff);
+ } else {
+ dF = params->dF_r;
+ }
+ ntru_elements_2_octets((uint16_t)dF << 1, privkey,
+ params->N_bits, privkey_blob);
+ }
+ break;
+ default:
+ assert(FALSE);
+ break;
+ }
+}
+
+
--- /dev/null
+/******************************************************************************
+ * 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_crypto_ntru_encrypt_param_sets.h"
+
+
+/* key-blob definitions */
+
+#define NTRU_ENCRYPT_PUBKEY_TAG 0x01
+#define NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG 0x02
+#define NTRU_ENCRYPT_PRIVKEY_TRITS_TAG 0xfe
+#define NTRU_ENCRYPT_PRIVKEY_INDICES_TAG 0xff
+
+/* packing types */
+
+#define NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS 0x01
+#define NTRU_ENCRYPT_KEY_PACKED_INDICES 0x02
+#define NTRU_ENCRYPT_KEY_PACKED_TRITS 0x03
+
+/* 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_ENCRYPT_PARAM_SET **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 */
+
+
+/* ntru_crypto_ntru_encrypt_key_get_blob_params
+ *
+ * Returns public and private key packing types and blob lengths given
+ * a packing format. For now, only a default packing format exists.
+ *
+ * Only public-key params may be returned by setting privkey_pack_type
+ * and privkey_blob_len to NULL.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_get_blob_params(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint8_t *pubkey_pack_type, /* out - addr for pubkey
+ packing type */
+ uint16_t *pubkey_blob_len, /* out - addr for no. of
+ bytes in
+ pubkey blob */
+ uint8_t *privkey_pack_type, /* out - addr for privkey
+ packing type */
+ uint16_t *privkey_blob_len); /* out - addr for no. of
+ bytes in
+ privkey blob */
+
+
+/* ntru_crypto_ntru_encrypt_key_create_pubkey_blob
+ *
+ * Returns a public key blob, packed according to the packing type provided.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_create_pubkey_blob(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint16_t const *pubkey, /* in - pointer to the
+ coefficients
+ of the pubkey */
+ uint8_t pubkey_pack_type, /* out - addr for pubkey
+ packing type */
+ uint8_t *pubkey_blob); /* out - addr for the
+ pubkey blob */
+
+
+/* ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob
+ *
+ * Returns a public key blob, recreated from an already-packed public key.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint16_t packed_pubkey_len, /* in - no. octets in
+ packed pubkey */
+ uint8_t const *packed_pubkey, /* in - pointer to the
+ packed pubkey */
+ uint8_t pubkey_pack_type, /* out - pubkey packing
+ type */
+ uint8_t *pubkey_blob); /* out - addr for the
+ pubkey blob */
+
+
+/* ntru_crypto_ntru_encrypt_key_create_privkey_blob
+ *
+ * Returns a privlic key blob, packed according to the packing type provided.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_create_privkey_blob(
+ NTRU_ENCRYPT_PARAM_SET const *params, /* in - pointer to
+ param set
+ parameters */
+ uint16_t const *pubkey, /* in - pointer to the
+ coefficients
+ of the pubkey */
+ uint16_t const *privkey, /* in - pointer to the
+ indices of the
+ privkey */
+ uint8_t privkey_pack_type, /* in - privkey packing
+ type */
+ uint8_t *buf, /* in - temp, N bytes */
+ uint8_t *privkey_blob); /* out - addr for the
+ privkey blob */
+
+
+#endif /* NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_param_sets.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_param_sets.c
+ *
+ * Contents: Defines the NTRUEncrypt parameter sets.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_ntru_encrypt_param_sets.h"
+
+
+/* parameter sets */
+
+static NTRU_ENCRYPT_PARAM_SET ntruParamSets[] = {
+
+ {
+ NTRU_EES401EP1, /* parameter-set id */
+ {0x00, 0x02, 0x04}, /* OID */
+ 0x22, /* DER id */
+ 9, /* no. of bits in N (i.e., in an index) */
+ 401, /* N */
+ 14, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 113, /* df, dr */
+ 133, /* dg */
+ 60, /* maxMsgLenBytes */
+ 113, /* dm0 */
+ 2005, /* 2^c - (2^c mod N) */
+ 11, /* c */
+ 1, /* lLen */
+ 32, /* min. no. of hash calls for IGF-2 */
+ 9, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES449EP1, /* parameter-set id */
+ {0x00, 0x03, 0x03}, /* OID */
+ 0x23, /* DER id */
+ 9, /* no. of bits in N (i.e., in an index) */
+ 449, /* N */
+ 16, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 134, /* df, dr */
+ 149, /* dg */
+ 67, /* maxMsgLenBytes */
+ 134, /* dm0 */
+ 449, /* 2^c - (2^c mod N) */
+ 9, /* c */
+ 1, /* lLen */
+ 31, /* min. no. of hash calls for IGF-2 */
+ 9, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES677EP1, /* parameter-set id */
+ {0x00, 0x05, 0x03}, /* OID */
+ 0x24, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 677, /* N */
+ 24, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 157, /* df, dr */
+ 225, /* dg */
+ 101, /* maxMsgLenBytes */
+ 157, /* dm0 */
+ 2031, /* 2^c - (2^c mod N) */
+ 11, /* c */
+ 1, /* lLen */
+ 27, /* min. no. of hash calls for IGF-2 */
+ 9, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES1087EP2, /* parameter-set id */
+ {0x00, 0x06, 0x03}, /* OID */
+ 0x25, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 1087, /* N */
+ 32, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 120, /* df, dr */
+ 362, /* dg */
+ 170, /* maxMsgLenBytes */
+ 120, /* dm0 */
+ 7609, /* 2^c - (2^c mod N) */
+ 13, /* c */
+ 1, /* lLen */
+ 25, /* min. no. of hash calls for IGF-2 */
+ 14, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES541EP1, /* parameter-set id */
+ {0x00, 0x02, 0x05}, /* OID */
+ 0x26, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 541, /* N */
+ 14, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 49, /* df, dr */
+ 180, /* dg */
+ 86, /* maxMsgLenBytes */
+ 49, /* dm0 */
+ 3787, /* 2^c - (2^c mod N) */
+ 12, /* c */
+ 1, /* lLen */
+ 15, /* min. no. of hash calls for IGF-2 */
+ 11, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES613EP1, /* parameter-set id */
+ {0x00, 0x03, 0x04}, /* OID */
+ 0x27, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 613, /* N */
+ 16, /* securuity strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 55, /* df, dr */
+ 204, /* dg */
+ 97, /* maxMsgLenBytes */
+ 55, /* dm0 */
+ 1839, /* 2^c - (2^c mod N) */
+ 11, /* c */
+ 1, /* lLen */
+ 16, /* min. no. of hash calls for IGF-2 */
+ 13, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES887EP1, /* parameter-set id */
+ {0x00, 0x05, 0x04}, /* OID */
+ 0x28, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 887, /* N */
+ 24, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 81, /* df, dr */
+ 295, /* dg */
+ 141, /* maxMsgLenBytes */
+ 81, /* dm0 */
+ 887, /* 2^c - (2^c mod N) */
+ 10, /* c */
+ 1, /* lLen */
+ 13, /* min. no. of hash calls for IGF-2 */
+ 12, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES1171EP1, /* parameter-set id */
+ {0x00, 0x06, 0x04}, /* OID */
+ 0x29, /* DER id */
+ 11, /* no. of bits in N (i.e., in an index) */
+ 1171, /* N */
+ 32, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 106, /* df, dr */
+ 390, /* dg */
+ 186, /* maxMsgLenBytes */
+ 106, /* dm0 */
+ 3513, /* 2^c - (2^c mod N) */
+ 12, /* c */
+ 1, /* lLen */
+ 20, /* min. no. of hash calls for IGF-2 */
+ 15, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES659EP1, /* parameter-set id */
+ {0x00, 0x02, 0x06}, /* OID */
+ 0x2a, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 659, /* N */
+ 14, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 38, /* df, dr */
+ 219, /* dg */
+ 108, /* maxMsgLenBytes */
+ 38, /* dm0 */
+ 1977, /* 2^c - (2^c mod N) */
+ 11, /* c */
+ 1, /* lLen */
+ 11, /* min. no. of hash calls for IGF-2 */
+ 14, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES761EP1, /* parameter-set id */
+ {0x00, 0x03, 0x05}, /* OID */
+ 0x2b, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 761, /* N */
+ 16, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 42, /* df, dr */
+ 253, /* dg */
+ 125, /* maxMsgLenBytes */
+ 42, /* dm0 */
+ 3805, /* 2^c - (2^c mod N) */
+ 12, /* c */
+ 1, /* lLen */
+ 13, /* min. no. of hash calls for IGF-2 */
+ 16, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES1087EP1, /* parameter-set id */
+ {0x00, 0x05, 0x05}, /* OID */
+ 0x2c, /* DER id */
+ 11, /* no. of bits in N (i.e., in an index) */
+ 1087, /* N */
+ 24, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 63, /* df, dr */
+ 362, /* dg */
+ 178, /* maxMsgLenBytes */
+ 63, /* dm0 */
+ 7609, /* 2^c - (2^c mod N) */
+ 13, /* c */
+ 1, /* lLen */
+ 13, /* min. no. of hash calls for IGF-2 */
+ 14, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES1499EP1, /* parameter-set id */
+ {0x00, 0x06, 0x05}, /* OID */
+ 0x2d, /* DER id */
+ 11, /* no. of bits in N (i.e., in an index) */
+ 1499, /* N */
+ 32, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ FALSE, /* product form */
+ 79, /* df, dr */
+ 499, /* dg */
+ 247, /* maxMsgLenBytes */
+ 79, /* dm0 */
+ 7495, /* 2^c - (2^c mod N) */
+ 13, /* c */
+ 1, /* lLen */
+ 17, /* min. no. of hash calls for IGF-2 */
+ 19, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES401EP2, /* parameter-set id */
+ {0x00, 0x02, 0x10}, /* OID */
+ 0x2e, /* DER id */
+ 9, /* no. of bits in N (i.e., in an index) */
+ 401, /* N */
+ 14, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ TRUE, /* product form */
+ 8 + (8 << 8) + (6 << 16), /* df, dr */
+ 133, /* dg */
+ 60, /* maxMsgLenBytes */
+ 136, /* m(1)_max */
+ 2005, /* 2^c - (2^c mod N) */
+ 11, /* c */
+ 1, /* lLen */
+ 10, /* min. no. of hash calls for IGF-2 */
+ 6, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES439EP1, /* parameter-set id */
+ {0x00, 0x03, 0x10}, /* OID */
+ 0x2f, /* DER id */
+ 9, /* no. of bits in N (i.e., in an index) */
+ 439, /* N */
+ 16, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ TRUE, /* product form */
+ 9 + (8 << 8) + (5 << 16), /* df, dr */
+ 146, /* dg */
+ 65, /* maxMsgLenBytes */
+ 126, /* m(1)_max */
+ 439, /* 2^c - (2^c mod N) */
+ 9, /* c */
+ 1, /* lLen */
+ 15, /* min. no. of hash calls for IGF-2 */
+ 6, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES593EP1, /* parameter-set id */
+ {0x00, 0x05, 0x10}, /* OID */
+ 0x30, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 593, /* N */
+ 24, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ TRUE, /* product form */
+ 10 + (10 << 8) + (8 << 16), /* df, dr */
+ 197, /* dg */
+ 86, /* maxMsgLenBytes */
+ 90, /* m(1)_max */
+ 1779, /* 2^c - (2^c mod N) */
+ 11, /* c */
+ 1, /* lLen */
+ 12, /* min. no. of hash calls for IGF-2 */
+ 5, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+ {
+ NTRU_EES743EP1, /* parameter-set id */
+ {0x00, 0x06, 0x10}, /* OID */
+ 0x31, /* DER id */
+ 10, /* no. of bits in N (i.e., in an index) */
+ 743, /* N */
+ 32, /* security strength in octets */
+ 2048, /* q */
+ 11, /* no. of bits in q (i.e., in a coeff) */
+ TRUE, /* product form */
+ 11 + (11 << 8) + (15 << 16), /* df, dr */
+ 247, /* dg */
+ 106, /* maxMsgLenBytes */
+ 60, /* m(1)_max */
+ 8173, /* 2^c - (2^c mod N) */
+ 13, /* c */
+ 1, /* lLen */
+ 12, /* min. no. of hash calls for IGF-2 */
+ 7, /* min. no. of hash calls for MGF-TP-1 */
+ },
+
+};
+
+static size_t numParamSets =
+ sizeof(ntruParamSets)/sizeof(NTRU_ENCRYPT_PARAM_SET);
+
+
+/* functions */
+
+/* ntru_encrypt_get_params_with_id
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_id(
+ NTRU_ENCRYPT_PARAM_SET_ID id) /* in - parameter-set id */
+{
+ size_t i;
+
+ for (i = 0; i < numParamSets; i++) {
+ if (ntruParamSets[i].id == id) {
+ return &(ntruParamSets[i]);
+ }
+ }
+ return NULL;
+}
+
+
+/* ntru_encrypt_get_params_with_OID
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the OID of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_OID(
+ uint8_t const *oid) /* in - pointer to parameter-set OID */
+{
+ size_t i;
+
+ for (i = 0; i < numParamSets; i++) {
+ if (!memcmp(ntruParamSets[i].OID, oid, 3)) {
+ return &(ntruParamSets[i]);
+ }
+ }
+ return NULL;
+}
+
+
+/* ntru_encrypt_get_params_with_DER_id
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the DER id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_DER_id(
+ uint8_t der_id) /* in - parameter-set DER id */
+{
+ size_t i;
+
+ for (i = 0; i < numParamSets; i++) {
+ if (ntruParamSets[i].der_id == der_id) {
+ return &(ntruParamSets[i]);
+ }
+ }
+ return NULL;
+}
+
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_encrypt_param_sets.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_encrypt_param_sets.h
+ *
+ * Contents: Definitions and declarations for the NTRUEncrypt parameter sets.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H
+#define NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H
+
+#include "ntru_crypto.h"
+#include "ntru_crypto_hash_basics.h"
+
+
+/* structures */
+
+typedef struct _NTRU_ENCRYPT_PARAM_SET {
+ NTRU_ENCRYPT_PARAM_SET_ID id; /* parameter-set ID */
+ uint8_t const OID[3]; /* pointer to OID */
+ uint8_t der_id; /* parameter-set DER id */
+ uint8_t N_bits; /* no. of bits in N (i.e. in
+ an index */
+ uint16_t N; /* ring dimension */
+ uint16_t sec_strength_len; /* no. of octets of
+ security strength */
+ uint16_t q; /* big modulus */
+ uint8_t q_bits; /* no. of bits in q (i.e. in
+ a coefficient */
+ bool is_product_form; /* if product form used */
+ uint32_t dF_r; /* no. of 1 or -1 coefficients
+ in ring elements F, r */
+ uint16_t dg; /* no. - 1 of 1 coefficients
+ or no. of -1 coefficients
+ in ring element g */
+ uint16_t m_len_max; /* max no. of plaintext
+ octets */
+ uint16_t min_msg_rep_wt; /* min. message
+ representative weight */
+ uint16_t no_bias_limit; /* limit for no bias in
+ IGF-2 */
+ uint8_t c_bits; /* no. bits in candidate for
+ deriving an index in
+ IGF-2 */
+ uint8_t m_len_len; /* no. of octets to hold
+ mLenOctets */
+ uint8_t min_IGF_hash_calls; /* min. no. of hash calls for
+ IGF-2 */
+ uint8_t min_MGF_hash_calls; /* min. no. of hash calls for
+ MGF-TP-1 */
+} NTRU_ENCRYPT_PARAM_SET;
+
+
+
+/* function declarations */
+
+/* ntru_encrypt_get_params_with_id
+ *
+ * Looks up a set of NTRU Encrypt parameters based on the id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+extern NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_id(
+ NTRU_ENCRYPT_PARAM_SET_ID id); /* in - parameter-set id */
+
+
+/* ntru_encrypt_get_params_with_OID
+ *
+ * Looks up a set of NTRU Encrypt parameters based on the OID of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+extern NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_OID(
+ uint8_t const *oid); /* in - pointer to parameter-set OID */
+
+
+/* ntru_encrypt_get_params_with_DER_id
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the DER id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+extern NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_DER_id(
+ uint8_t der_id); /* in - parameter-set DER id */
+
+
+#endif /* NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H */
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_mgf1.c is a component of ntru-crypto.
+ *
+ * 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_mgf1.c
+ *
+ * Contents: Routines implementing MGF-TP-1 and MGF-1.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_mgf1.h"
+#include "ntru_crypto_ntru_convert.h"
+
+
+/* ntru_mgf1
+ *
+ * Implements a basic mask-generation function, generating an arbitrary
+ * number of octets based on hashing a digest-length string concatenated
+ * with a 4-octet counter.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+uint32_t
+ntru_mgf1(
+ uint8_t *state, /* in/out - pointer to the state */
+ NTRU_CRYPTO_HASH_ALGID algid, /* in - hash algorithm ID */
+ uint8_t md_len, /* in - no. of octets in digest */
+ uint8_t num_calls, /* in - no. of hash calls */
+ uint16_t seed_len, /* in - no. of octets in seed */
+ uint8_t const *seed, /* in - pointer to seed */
+ uint8_t *out) /* out - address for output */
+{
+ uint8_t *ctr = state + md_len;
+ uint32_t retcode;
+
+ assert(state);
+ assert(out);
+
+ /* if seed present, init state */
+
+ if (seed) {
+ if ((retcode = ntru_crypto_hash_digest(algid, seed, seed_len, state)) !=
+ NTRU_CRYPTO_HASH_OK)
+ return retcode;
+ memset(ctr, 0, 4);
+ }
+
+ /* generate output */
+
+ while (num_calls-- > 0) {
+ if ((retcode = ntru_crypto_hash_digest(algid, state, md_len + 4,
+ out)) !=
+ NTRU_CRYPTO_HASH_OK)
+ return retcode;
+ out += md_len;
+
+ /* increment counter */
+
+ if (++ctr[3] == 0)
+ if (++ctr[2] == 0)
+ if (++ctr[1] == 0)
+ ++ctr[0];
+ }
+
+ NTRU_RET(NTRU_OK);
+}
+
+
+/* ntru_mgftp1
+ *
+ * Implements a mask-generation function for trinary polynomials,
+ * MGF-TP-1, generating an arbitrary number of octets based on hashing
+ * a digest-length string concatenated with a 4-octet counter. From
+ * these octets, N trits are derived.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+uint32_t
+ntru_mgftp1(
+ NTRU_CRYPTO_HASH_ALGID hash_algid, /* in - hash alg ID for
+ MGF-TP-1 */
+ uint8_t md_len, /* in - no. of octets in
+ digest */
+ uint8_t min_calls, /* in - minimum no. of hash
+ calls */
+ uint16_t seed_len, /* in - no. of octets in seed */
+ uint8_t *seed, /* in - pointer to seed */
+ uint8_t *buf, /* in - pointer to working
+ buffer */
+ uint16_t num_trits_needed, /* in - no. of trits in mask */
+ uint8_t *mask) /* out - address for mask trits */
+{
+ uint8_t *mgf_out;
+ uint8_t *octets;
+ uint16_t octets_available;
+ uint32_t retcode;
+
+ assert(seed);
+ assert(buf);
+ assert(mask);
+
+ /* generate minimum MGF1 output */
+
+ mgf_out = buf + md_len + 4;
+ if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
+ seed_len, seed, mgf_out)) != NTRU_OK)
+ return retcode;
+ octets = mgf_out;
+ octets_available = min_calls * md_len;
+
+ /* get trits for mask */
+
+ while (num_trits_needed >= 5) {
+
+ /* get another octet and convert it to 5 trits */
+
+ if (octets_available == 0) {
+ if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
+ 0, NULL, mgf_out)) != NTRU_OK)
+ return retcode;
+ octets = mgf_out;
+ octets_available = md_len;
+ }
+
+ if (*octets < 243) {
+ ntru_octet_2_trits(*octets, mask);
+ mask += 5;
+ num_trits_needed -= 5;
+ }
+ octets++;
+ --octets_available;
+ }
+
+ /* get any remaining trits */
+
+ while (num_trits_needed) {
+ uint8_t trits[5];
+
+ /* get another octet and convert it to remaining trits */
+
+ if (octets_available == 0) {
+ if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
+ 0, NULL, mgf_out)) != NTRU_OK)
+ return retcode;
+ octets = mgf_out;
+ octets_available = md_len;
+ }
+ if (*octets < 243) {
+ ntru_octet_2_trits(*octets, trits);
+ memcpy(mask, trits, num_trits_needed);
+ num_trits_needed = 0;
+ } else {
+ octets++;
+ --octets_available;
+ }
+ }
+
+ NTRU_RET(NTRU_OK);
+}
+
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_mgf1.h is a component of ntru-crypto.
+ *
+ * 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_mgf1.h
+ *
+ * Contents: Public header file for MGF-1 in the NTRU algorithm.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_NTRU_MGF1_H
+#define NTRU_CRYPTO_NTRU_MGF1_H
+
+
+#include "ntru_crypto.h"
+#include "ntru_crypto_hash.h"
+
+
+/* function declarations */
+
+/* ntru_mgf1
+ *
+ * Implements a basic mask-generation function, generating an arbitrary
+ * number of octets based on hashing a digest-length string concatenated
+ * with a 4-octet counter.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+extern uint32_t
+ntru_mgf1(
+ uint8_t *state, /* in/out - pointer to the state */
+ NTRU_CRYPTO_HASH_ALGID algid, /* in - hash algorithm ID */
+ uint8_t md_len, /* in - no. of octets in digest */
+ uint8_t num_calls, /* in - no. of hash calls */
+ uint16_t seed_len, /* in - no. of octets in seed */
+ uint8_t const *seed, /* in - pointer to seed */
+ uint8_t *out); /* out - address for output */
+
+
+/* ntru_mgftp1
+ *
+ * Implements a mask-generation function for trinary polynomials,
+ * MGF-TP-1, generating an arbitrary number of octets based on hashing
+ * a digest-length string concatenated with a 4-octet counter. From
+ * these octets, N trits are derived.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+extern uint32_t
+ntru_mgftp1(
+ NTRU_CRYPTO_HASH_ALGID hash_algid, /* in - hash alg ID for
+ MGF-TP-1 */
+ uint8_t md_len, /* in - no. of octets in
+ digest */
+ uint8_t min_calls, /* in - minimum no. of hash
+ calls */
+ uint16_t seed_len, /* in - no. of octets in seed */
+ uint8_t *seed, /* in - pointer to seed */
+ uint8_t *buf, /* in - pointer to working
+ buffer */
+ uint16_t num_trits_needed, /* in - no. of trits in mask */
+ uint8_t *mask); /* out - address for mask trits */
+
+
+#endif /* NTRU_CRYPTO_NTRU_MGF1_H */
--- /dev/null
+/******************************************************************************
+ * 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.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_poly.c
+ *
+ * Contents: Routines for generating and operating on polynomials in the
+ * NTRU algorithm.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_poly.h"
+#include "ntru_crypto_ntru_mgf1.h"
+
+
+/* ntru_gen_poly
+ *
+ * Generates polynomials by creating for each polynomial, a list of the
+ * indices of the +1 coefficients followed by a list of the indices of
+ * the -1 coefficients.
+ *
+ * If a single polynomial is generated (non-product form), indices_counts
+ * contains a single value of the total number of indices (for +1 and -1
+ * comefficients combined).
+ *
+ * If multiple polynomials are generated (for product form), their lists of
+ * indices are sequentially stored in the indices buffer. Each byte of
+ * indices_counts contains the total number of indices (for +1 and -1
+ * coefficients combined) for a single polynomial, beginning with the
+ * low-order byte for the first polynomial. The high-order byte is unused.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns HASH_BAD_ALG if the algorithm is not supported.
+ *
+ */
+
+uint32_t
+ntru_gen_poly(
+ NTRU_CRYPTO_HASH_ALGID hash_algid, /* in - hash algorithm ID for
+ IGF-2 */
+ uint8_t md_len, /* in - no. of octets in digest */
+ uint8_t min_calls, /* in - minimum no. of hash
+ calls */
+ uint16_t seed_len, /* in - no. of octets in seed */
+ uint8_t *seed, /* in - pointer to seed */
+ uint8_t *buf, /* in - pointer to working
+ buffer */
+ uint16_t N, /* in - max index + 1 */
+ uint8_t c_bits, /* in - no. bits for candidate */
+ uint16_t limit, /* in - conversion to index
+ limit */
+ bool is_product_form, /* in - if generating multiple
+ polys */
+ uint32_t indices_counts, /* in - nos. of indices needed */
+ uint16_t *indices) /* out - address for indices */
+{
+ uint8_t *mgf_out;
+ uint8_t *octets;
+ uint8_t *used;
+ uint8_t num_polys;
+ uint16_t num_indices;
+ uint16_t octets_available;
+ uint16_t index_cnt = 0;
+ uint8_t left = 0;
+ uint8_t num_left = 0;
+ uint32_t retcode;
+
+ assert(seed);
+ assert(buf);
+ assert(indices);
+
+ /* generate minimum MGF1 output */
+
+ mgf_out = buf + md_len + 4;
+ if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
+ seed_len, seed, mgf_out)) != NTRU_OK)
+ return retcode;
+ octets = mgf_out;
+ octets_available = min_calls * md_len;
+
+ /* init indices counts for number of polynomials being generated */
+
+ if (is_product_form) {
+
+ /* number of indices for poly1 is in low byte of indices_counts,
+ * number of indices for poly2 and poly3 are in next higher bytes
+ */
+
+ num_polys = 3;
+ num_indices = (uint16_t)(indices_counts & 0xff);
+ indices_counts >>= 8;
+
+ } else {
+
+ /* number of bytes for poly is in low 16 bits of indices_counts */
+
+ num_polys = 1;
+ num_indices = (uint16_t)indices_counts;
+ }
+
+ /* init used-index array */
+
+ used = mgf_out + octets_available;
+ memset(used, 0, N);
+
+ /* generate indices (IGF-2) for all polynomials */
+
+ while (num_polys > 0) {
+
+ /* generate indices for a single polynomial */
+
+ while (index_cnt < num_indices) {
+ uint16_t index;
+ uint8_t num_needed;
+
+ /* form next index to convert to an index */
+
+ do {
+ /* use any leftover bits first */
+
+ if (num_left != 0) {
+ index = left << (c_bits - num_left);
+ } else {
+ index = 0;
+ }
+
+ /* get the rest of the bits needed from new octets */
+
+ num_needed = c_bits - num_left;
+ while (num_needed != 0) {
+
+ /* get another octet */
+
+ if (octets_available == 0) {
+ if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
+ 0, NULL, mgf_out)) != NTRU_OK)
+ return retcode;
+ octets = mgf_out;
+ octets_available = md_len;
+ }
+ left = *octets++;
+ --octets_available;
+
+ if (num_needed <= 8) {
+
+ /* all bits needed to fill the index are in this octet */
+
+ index |= ((uint16_t)(left)) >> (8 - num_needed);
+ num_left = 8 - num_needed;
+ num_needed = 0;
+ left &= 0xff >> (8 - num_left);
+
+ } else {
+
+ /* another octet will be needed after using this
+ * whole octet
+ */
+
+ index |= ((uint16_t)left) << (num_needed - 8);
+ num_needed -= 8;
+ }
+ }
+ } while (index >= limit);
+
+ /* form index and check if unique */
+
+ index %= N;
+ if (!used[index]) {
+ used[index] = 1;
+ indices[index_cnt] = index;
+ ++index_cnt;
+ }
+ }
+ --num_polys;
+
+ /* init for next polynomial if another polynomial to be generated */
+
+ if (num_polys > 0) {
+ memset(used, 0, N);
+ num_indices = num_indices +
+ (uint16_t)(indices_counts & 0xff);
+ indices_counts >>= 8;
+ }
+ }
+
+ NTRU_RET(NTRU_OK);
+}
+
+
+/* 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;
+}
+
+
+/* ntru_ring_mult_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is a sparse trinary polynomial with coefficients -1, 0,
+ * and 1. It is specified by a list, bi, of its nonzero indices containing
+ * indices for the bi_P1_len +1 coefficients followed by the indices for the
+ * bi_M1_len -1 coefficients.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * input array "b", or temp array "t".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+void
+ntru_ring_mult_indices(
+ uint16_t const *a, /* in - pointer to ring element a */
+ uint16_t bi_P1_len, /* in - no. of +1 coefficients in b */
+ uint16_t bi_M1_len, /* in - no. of -1 coefficients in b */
+ uint16_t const *bi, /* in - pointer to the list of nonzero
+ indices of ring element b,
+ containing indices for the +1
+ coefficients followed by the
+ indices for -1 coefficients */
+ uint16_t N, /* in - no. of coefficients in a, b, c */
+ uint16_t q, /* in - large modulus */
+ uint16_t *t, /* in - temp buffer of N elements */
+ uint16_t *c) /* out - address for polynomial c */
+{
+ uint16_t mod_q_mask = q - 1;
+ uint16_t i, j, k;
+
+ assert(a);
+ assert(bi);
+ assert(t);
+ assert(c);
+
+ /* t[(i+k)%N] = sum i=0 through N-1 of a[i], for b[k] = -1 */
+
+ for (k = 0; k < N; k++)
+ t[k] = 0;
+ for (j = bi_P1_len; j < bi_P1_len + bi_M1_len; j++) {
+ k = bi[j];
+ for (i = 0; k < N; ++i, ++k)
+ t[k] = t[k] + a[i];
+ for (k = 0; i < N; ++i, ++k)
+ t[k] = t[k] + a[i];
+ }
+
+ /* t[(i+k)%N] = -(sum i=0 through N-1 of a[i] for b[k] = -1) */
+
+ for (k = 0; k < N; k++)
+ t[k] = -t[k];
+
+ /* t[(i+k)%N] += sum i=0 through N-1 of a[i] for b[k] = +1 */
+
+ for (j = 0; j < bi_P1_len; j++) {
+ k = bi[j];
+ for (i = 0; k < N; ++i, ++k)
+ t[k] = t[k] + a[i];
+ for (k = 0; i < N; ++i, ++k)
+ t[k] = t[k] + a[i];
+ }
+
+ /* c = (a * b) mod q */
+
+ for (k = 0; k < N; k++)
+ c[k] = t[k] & mod_q_mask;
+}
+
+
+/* ntru_ring_mult_product_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is represented by the product form b1 * b2 + b3, where
+ * b1, b2, and b3 are each a sparse trinary polynomial with coefficients -1,
+ * 0, and 1. It is specified by a list, bi, of the nonzero indices of b1, b2,
+ * and b3, containing the indices for the +1 coefficients followed by the
+ * indices for the -1 coefficients for each polynomial in that order.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * or input array "b".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+void
+ntru_ring_mult_product_indices(
+ uint16_t *a, /* in - pointer to ring element a */
+ uint16_t b1i_len, /* in - no. of +1 or -1 coefficients in b1 */
+ uint16_t b2i_len, /* in - no. of +1 or -1 coefficients in b2 */
+ uint16_t b3i_len, /* in - no. of +1 or -1 coefficients in b3 */
+ uint16_t const *bi, /* in - pointer to the list of nonzero
+ indices of polynomials b1, b2, b3,
+ containing indices for the +1
+ coefficients followed by the
+ indices for -1 coefficients for
+ each polynomial */
+ uint16_t N, /* in - no. of coefficients in a, b, c */
+ uint16_t q, /* in - large modulus */
+ uint16_t *t, /* in - temp buffer of 2N elements */
+ uint16_t *c) /* out - address for polynomial c */
+{
+ uint16_t *t2 = t + N;
+ uint16_t mod_q_mask = q - 1;
+ uint16_t i;
+
+ assert(a);
+ assert(bi);
+ assert(t);
+ assert(c);
+
+ /* t2 = a * b1 */
+
+ ntru_ring_mult_indices(a, b1i_len, b1i_len, bi, N, q, t, t2);
+
+ /* t2 = (a * b1) * b2 */
+
+ ntru_ring_mult_indices(t2, b2i_len, b2i_len, bi + (b1i_len << 1), N, q,
+ t, t2);
+
+ /* t = a * b3 */
+
+ ntru_ring_mult_indices(a, b3i_len, b3i_len,
+ bi + ((b1i_len + b2i_len) << 1), N, q, t, t);
+
+ /* c = (a * b1 * b2) + (a * b3) */
+
+ for (i = 0; i < N; i++)
+ c[i] = (t2[i] + t[i]) & mod_q_mask;
+}
+
+
+/* ntru_ring_mult_coefficients
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" has coefficients in the range [0,N).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+void
+ntru_ring_mult_coefficients(
+ uint16_t const *a, /* in - pointer to polynomial a */
+ uint16_t const *b, /* in - pointer to polynomial b */
+ uint16_t N, /* in - no. of coefficients in a, b, c */
+ uint16_t q, /* in - large modulus */
+ uint16_t *c) /* out - address for polynomial c */
+{
+ uint16_t const *bptr = b;
+ uint16_t mod_q_mask = q - 1;
+ uint16_t i, k;
+
+ assert(a);
+ assert(b);
+ assert(c);
+
+ /* c[k] = sum(a[i] * b[k-i]) mod q */
+
+ memset(c, 0, N * sizeof(uint16_t));
+ for (k = 0; k < N; k++) {
+ i = 0;
+ while (i <= k)
+ c[k] += a[i++] * *bptr--;
+ bptr += N;
+ while (i < N)
+ c[k] += a[i++] * *bptr--;
+ c[k] &= mod_q_mask;
+ ++bptr;
+ }
+}
+
+
+/* ntru_ring_inv
+ *
+ * Finds the inverse of a polynomial, a, in (Z/2^rZ)[X]/(X^N - 1).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that operations mod q can
+ * wait until the end, and only 16-bit arrays need to be used.
+ */
+
+bool
+ntru_ring_inv(
+ uint16_t *a, /* in - pointer to polynomial a */
+ uint16_t N, /* in - no. of coefficients in a */
+ uint16_t q, /* in - large modulus */
+ uint16_t *t, /* in - temp buffer of 2N elements */
+ uint16_t *a_inv) /* out - address for polynomial a^-1 */
+{
+ uint8_t *b = (uint8_t *)t; /* b cannot be in a_inv since it must be
+ rotated and copied there as a^-1 mod 2 */
+ uint8_t *c = b + N; /* c cannot be in a_inv since it exchanges
+ with b, and b cannot be in a_inv */
+ uint8_t *f = c + N;
+ uint8_t *g = (uint8_t *)a_inv; /* g needs N + 1 bytes */
+ uint16_t *t2 = t + N;
+ uint16_t deg_b;
+ uint16_t deg_c;
+ uint16_t deg_f;
+ uint16_t deg_g;
+ uint16_t k = 0;
+ bool done = FALSE;
+ uint16_t i, j;
+
+ assert(a);
+ assert(t);
+ assert(a_inv);
+
+ /* form a^-1 in (Z/2Z)[X]/X^N - 1) */
+
+ memset(b, 0, (N << 1)); /* clear to init b, c */
+
+ /* b(X) = 1 */
+
+ b[0] = 1;
+ deg_b = 0;
+
+ /* c(X) = 0 (cleared above) */
+
+ deg_c = 0;
+
+ /* f(X) = a(X) mod 2 */
+
+ for (i = 0; i < N; i++)
+ f[i] = (uint8_t)(a[i] & 1);
+ deg_f = N - 1;
+
+ /* g(X) = X^N - 1 */
+
+ g[0] = 1;
+ memset(g + 1, 0, N - 1);
+ g[N] = 1;
+ deg_g = N;
+
+ /* until f(X) = 1 */
+
+ while (!done) {
+
+ /* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */
+
+ for (i = 0; (i <= deg_f) && (f[i] == 0); ++i);
+ if (i > deg_f)
+ return FALSE;
+ if (i) {
+ f = f + i;
+ deg_f = deg_f - i;
+ deg_c = deg_c + i;
+ for (j = deg_c; j >= i; j--)
+ c[j] = c[j-i];
+ for (j = 0; j < i; j++)
+ c[j] = 0;
+ k = k + i;
+ }
+
+ /* adjust degree of f(X) if the highest coefficients are zero
+ * Note: f[0] = 1 from above so the loop will terminate.
+ */
+
+ while (f[deg_f] == 0)
+ --deg_f;
+
+ /* if f(X) = 1, done
+ * Note: f[0] = 1 from above, so only check the x term and up
+ */
+
+ for (i = 1; (i <= deg_f) && (f[i] == 0); ++i);
+ if (i > deg_f) {
+ done = TRUE;
+ break;
+ }
+
+ /* if deg_f < deg_g, f <-> g, b <-> c */
+
+ if (deg_f < deg_g) {
+ uint8_t *x;
+
+ x = f;
+ f = g;
+ g = x;
+ deg_f ^= deg_g;
+ deg_g ^= deg_f;
+ deg_f ^= deg_g;
+ x = b;
+ b = c;
+ c = x;
+ deg_b ^= deg_c;
+ deg_c ^= deg_b;
+ deg_b ^= deg_c;
+ }
+
+ /* f(X) += g(X), b(X) += c(X) */
+
+ for (i = 0; i <= deg_g; i++)
+ f[i] ^= g[i];
+
+ if (deg_c > deg_b)
+ deg_b = deg_c;
+ for (i = 0; i <= deg_c; i++)
+ b[i] ^= c[i];
+ }
+
+ /* a^-1 in (Z/2Z)[X]/(X^N - 1) = b(X) shifted left k coefficients */
+
+ j = 0;
+ if (k >= N)
+ k = k - N;
+ for (i = k; i < N; i++)
+ a_inv[j++] = (uint16_t)(b[i]);
+ for (i = 0; i < k; i++)
+ a_inv[j++] = (uint16_t)(b[i]);
+
+ /* lift a^-1 in (Z/2Z)[X]/(X^N - 1) to a^-1 in (Z/qZ)[X]/(X^N -1) */
+
+ for (j = 0; j < 4; ++j) { /* assumes 256 < q <= 65536 */
+
+ /* a^-1 = a^-1 * (2 - a * a^-1) mod q */
+
+ memcpy(t2, a_inv, N * sizeof(uint16_t));
+ ntru_ring_mult_coefficients(a, t2, N, q, t);
+ for (i = 0; i < N; ++i)
+ t[i] = q - t[i];
+ t[0] = t[0] + 2;
+ ntru_ring_mult_coefficients(t2, t, N, q, a_inv);
+ }
+
+ return TRUE;
+
+
+}
+
+
--- /dev/null
+/******************************************************************************
+ * 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 "ntru_crypto_hash_basics.h"
+
+
+/* function declarations */
+
+/* ntru_gen_poly
+ *
+ * Generates polynomials by creating for each polynomial, a list of the
+ * indices of the +1 coefficients followed by a list of the indices of
+ * the -1 coefficients.
+ *
+ * If a single polynomial is generated (non-product form), indices_counts
+ * contains a single value of the total number of indices (for +1 and -1
+ * comefficients combined).
+ *
+ * If multiple polynomials are generated (for product form), their lists of
+ * indices are sequentially stored in the indices buffer. Each byte of
+ * indices_counts contains the total number of indices (for +1 and -1
+ * coefficients combined) for a single polynomial, beginning with the
+ * low-order byte for the first polynomial. The high-order byte is unused.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns HASH_BAD_ALG if the algorithm is not supported.
+ *
+ */
+
+extern uint32_t
+ntru_gen_poly(
+ NTRU_CRYPTO_HASH_ALGID hash_algid, /* in - hash algorithm ID for
+ IGF-2 */
+ uint8_t md_len, /* in - no. of octets in digest */
+ uint8_t min_calls, /* in - minimum no. of hash
+ calls */
+ uint16_t seed_len, /* in - no. of octets in seed */
+ uint8_t *seed, /* in - pointer to seed */
+ uint8_t *buf, /* in - pointer to working
+ buffer */
+ uint16_t N, /* in - max index + 1 */
+ uint8_t c_bits, /* in - no. bits for candidate */
+ uint16_t limit, /* in - conversion to index
+ limit */
+ bool is_product_form, /* in - if generating multiple
+ polys */
+ uint32_t indices_counts, /* in - nos. of indices needed */
+ uint16_t *indices); /* out - address for indices */
+
+
+/* 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 */
+
+
+/* ntru_ring_mult_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is a sparse trinary polynomial with coefficients -1, 0,
+ * and 1. It is specified by a list, bi, of its nonzero indices containing
+ * indices for the bi_P1_len +1 coefficients followed by the indices for the
+ * bi_M1_len -1 coefficients.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * or input array "b".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+extern void
+ntru_ring_mult_indices(
+ uint16_t const *a, /* in - pointer to ring element a */
+ uint16_t bi_P1_len, /* in - no. of +1 coefficients in b */
+ uint16_t bi_M1_len, /* in - no. of -1 coefficients in b */
+ uint16_t const *bi, /* in - pointer to the list of nonzero
+ indices of ring element b,
+ containing indices for the +1
+ coefficients followed by the
+ indices for -1 coefficients */
+ uint16_t N, /* in - no. of coefficients in a, b, c */
+ uint16_t q, /* in - large modulus */
+ uint16_t *t, /* in - temp buffer of N elements */
+ uint16_t *c); /* out - address for polynomial c */
+
+
+/* ntru_ring_mult_product_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is represented by the product form b1 * b2 + b3, where
+ * b1, b2, and b3 are each a sparse trinary polynomial with coefficients -1,
+ * 0, and 1. It is specified by a list, bi, of the nonzero indices of b1, b2,
+ * and b3, containing the indices for the +1 coefficients followed by the
+ * indices for the -1 coefficients for each polynomial in that order.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * or input array "b".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+extern void
+ntru_ring_mult_product_indices(
+ uint16_t *a, /* in - pointer to ring element a */
+ uint16_t b1i_len, /* in - no. of +1 or -1 coefficients in b1 */
+ uint16_t b2i_len, /* in - no. of +1 or -1 coefficients in b2 */
+ uint16_t b3i_len, /* in - no. of +1 or -1 coefficients in b3 */
+ uint16_t const *bi, /* in - pointer to the list of nonzero
+ indices of polynomials b1, b2, b3,
+ containing indices for the +1
+ coefficients followed by the
+ indices for -1 coefficients for
+ each polynomial */
+ uint16_t N, /* in - no. of coefficients in a, b, c */
+ uint16_t q, /* in - large modulus */
+ uint16_t *t, /* in - temp buffer of 2N elements */
+ uint16_t *c); /* out - address for polynomial c */
+
+
+/* ntru_ring_mult_coefficients
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" has coefficients in the range [0,N).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+extern void
+ntru_ring_mult_coefficients(
+ uint16_t const *a, /* in - pointer to polynomial a */
+ uint16_t const *b, /* in - pointer to polynomial b */
+ uint16_t N, /* in - no. of coefficients in a, b, c */
+ uint16_t q, /* in - large modulus */
+ uint16_t *c); /* out - address for polynomial c */
+
+
+/* ntru_ring_inv
+ *
+ * Finds the inverse of a polynomial, a, in (Z/2^rZ)[X]/(X^N - 1).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that operations mod q can
+ * wait until the end, and only 16-bit arrays need to be used.
+ */
+
+extern bool
+ntru_ring_inv(
+ uint16_t *a, /* in - pointer to polynomial a */
+ uint16_t N, /* in - no. of coefficients in a */
+ uint16_t q, /* in - large modulus */
+ uint16_t *t, /* in - temp buffer of 2N elements */
+ uint16_t *a_inv); /* out - address for polynomial a^-1 */
+
+
+#endif /* NTRU_CRYPTO_NTRU_POLY_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_platform.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_platform.h
+ *
+ * Contents: Platform-specific basic definitions.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_PLATFORM_H
+#define NTRU_CRYPTO_PLATFORM_H
+
+#include <library.h>
+
+#endif /* NTRU_CRYPTO_PLATFORM_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_sha.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_sha.h
+ *
+ * Contents: Definitions and declarations common to all SHA hash algorithms.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_SHA_H
+#define NTRU_CRYPTO_SHA_H
+
+
+#include "ntru_crypto_error.h"
+#include "ntru_crypto_hash_basics.h"
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define SHA_OK ((uint32_t)NTRU_CRYPTO_HASH_OK)
+#define SHA_FAIL ((uint32_t)NTRU_CRYPTO_HASH_FAIL)
+#define SHA_BAD_PARAMETER ((uint32_t)NTRU_CRYPTO_HASH_BAD_PARAMETER)
+#define SHA_OVERFLOW ((uint32_t)NTRU_CRYPTO_HASH_OVERFLOW)
+
+#define SHA_RESULT(r) ((uint32_t)((r) ? SHA_ERROR_BASE + (r) : (r)))
+#define SHA_RET(r) return SHA_RESULT(r);
+
+
+/*********
+ * flags *
+ *********/
+
+#define SHA_DATA_ONLY HASH_DATA_ONLY
+#define SHA_INIT HASH_INIT
+#define SHA_FINISH HASH_FINISH
+#define SHA_ZERO_PAD HASH_ZERO_PAD
+
+
+#endif /* NTRU_CRYPTO_SHA_H */
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_ntru_crypto_sha1.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_sha1.c
+ *
+ * Contents: Routines implementing the SHA-1 hash calculation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_sha1.h"
+#include "ntru_crypto_msbyte_uint32.h"
+
+
+/* chaining state elements */
+
+#define H0 state[0]
+#define H1 state[1]
+#define H2 state[2]
+#define H3 state[3]
+#define H4 state[4]
+
+
+/* standard SHA-1 initialization values */
+
+#define H0_INIT 0x67452301UL
+#define H1_INIT 0xefcdab89UL
+#define H2_INIT 0x98badcfeUL
+#define H3_INIT 0x10325476UL
+#define H4_INIT 0xc3d2e1f0UL
+
+
+/* sha1_blk()
+ *
+ * This routine updates the current hash output (chaining state)
+ * by performing SHA-1 on a 512-bit block of data represented as sixteen
+ * 32-bit words.
+ */
+
+#define K00_19 0x5a827999UL
+#define K20_39 0x6ed9eba1UL
+#define K40_59 0x8f1bbcdcUL
+#define K60_79 0xca62c1d6UL
+
+#define RL(a, n) ( ((a) << (n)) | ((a) >> (32 - (n))) )
+
+
+static void
+sha1_blk(
+ uint32_t const *data, // in - ptr to 16 32-bit word input block
+ uint32_t *state) // in/out - ptr to 5 32-bit word chaining state
+{
+ uint32_t A, B, C, D, E;
+ uint32_t w[16];
+
+ /* init A - E */
+
+ A = H0; B = H1; C = H2; D = H3; E = H4;
+
+ /* rounds 0 - 15 */
+
+ E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[ 0]; B = RL(B, 30);
+ D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + data[ 1]; A = RL(A, 30);
+ C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + data[ 2]; E = RL(E, 30);
+ B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + data[ 3]; D = RL(D, 30);
+ A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + data[ 4]; C = RL(C, 30);
+ E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[ 5]; B = RL(B, 30);
+ D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + data[ 6]; A = RL(A, 30);
+ C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + data[ 7]; E = RL(E, 30);
+ B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + data[ 8]; D = RL(D, 30);
+ A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + data[ 9]; C = RL(C, 30);
+ E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[10]; B = RL(B, 30);
+ D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + data[11]; A = RL(A, 30);
+ C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + data[12]; E = RL(E, 30);
+ B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + data[13]; D = RL(D, 30);
+ A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + data[14]; C = RL(C, 30);
+ E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[15]; B = RL(B, 30);
+
+ /* rounds 16 - 19 */
+
+ w[ 0] = data[ 0] ^ data[ 2] ^ data[ 8] ^ data[13]; w[ 0] = RL(w[0], 1);
+ D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + w[ 0]; A = RL(A, 30);
+ w[ 1] = data[ 1] ^ data[ 3] ^ data[ 9] ^ data[14]; w[ 1] = RL(w[1], 1);
+ C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + w[ 1]; E = RL(E, 30);
+ w[ 2] = data[ 2] ^ data[ 4] ^ data[10] ^ data[15]; w[ 2] = RL(w[ 2], 1);
+ B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + w[ 2]; D = RL(D, 30);
+ w[ 3] = data[ 3] ^ data[ 5] ^ data[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+ A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + w[ 3]; C = RL(C, 30);
+
+ /* rounds 20 - 39 */
+
+ w[ 4] = data[ 4] ^ data[ 6] ^ data[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+ E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[ 4]; B = RL(B, 30);
+ w[ 5] = data[ 5] ^ data[ 7] ^ data[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+ D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[ 5]; A = RL(A, 30);
+ w[ 6] = data[ 6] ^ data[ 8] ^ data[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+ C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[ 6]; E = RL(E, 30);
+ w[ 7] = data[ 7] ^ data[ 9] ^ data[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+ B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[ 7]; D = RL(D, 30);
+ w[ 8] = data[ 8] ^ data[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+ A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[ 8]; C = RL(C, 30);
+ w[ 9] = data[ 9] ^ data[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+ E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[ 9]; B = RL(B, 30);
+ w[10] = data[10] ^ data[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+ D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[10]; A = RL(A, 30);
+ w[11] = data[11] ^ data[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+ C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[11]; E = RL(E, 30);
+ w[12] = data[12] ^ data[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+ B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[12]; D = RL(D, 30);
+ w[13] = data[13] ^ data[15] ^ w[ 5] ^ w[10]; w[13] = RL(w[13], 1);
+ A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[13]; C = RL(C, 30);
+ w[14] = data[14] ^ w[ 0] ^ w[ 6] ^ w[11]; w[14] = RL(w[14], 1);
+ E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[14]; B = RL(B, 30);
+ w[15] = data[15] ^ w[ 1] ^ w[ 7] ^ w[12]; w[15] = RL(w[15], 1);
+ D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[15]; A = RL(A, 30);
+ w[ 0] = w[ 0] ^ w[ 2] ^ w[ 8] ^ w[13]; w[ 0] = RL(w[ 0], 1);
+ C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[ 0]; E = RL(E, 30);
+ w[ 1] = w[ 1] ^ w[ 3] ^ w[ 9] ^ w[14]; w[ 1] = RL(w[ 1], 1);
+ B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[ 1]; D = RL(D, 30);
+ w[ 2] = w[ 2] ^ w[ 4] ^ w[10] ^ w[15]; w[ 2] = RL(w[ 2], 1);
+ A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[ 2]; C = RL(C, 30);
+ w[ 3] = w[ 3] ^ w[ 5] ^ w[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+ E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[ 3]; B = RL(B, 30);
+ w[ 4] = w[ 4] ^ w[ 6] ^ w[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+ D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[ 4]; A = RL(A, 30);
+ w[ 5] = w[ 5] ^ w[ 7] ^ w[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+ C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[ 5]; E = RL(E, 30);
+ w[ 6] = w[ 6] ^ w[ 8] ^ w[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+ B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[ 6]; D = RL(D, 30);
+ w[ 7] = w[ 7] ^ w[ 9] ^ w[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+ A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[ 7]; C = RL(C, 30);
+
+ /* rounds 40 - 59 */
+
+ w[ 8] = w[ 8] ^ w[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+ E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[ 8]; B = RL(B, 30);
+ w[ 9] = w[ 9] ^ w[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+ D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[ 9]; A = RL(A, 30);
+ w[10] = w[10] ^ w[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+ C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[10]; E = RL(E, 30);
+ w[11] = w[11] ^ w[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+ B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[11]; D = RL(D, 30);
+ w[12] = w[12] ^ w[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+ A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[12]; C = RL(C, 30);
+ w[13] = w[13] ^ w[15] ^ w[ 5] ^ w[10]; w[13] = RL(w[13], 1);
+ E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[13]; B = RL(B, 30);
+ w[14] = w[14] ^ w[ 0] ^ w[ 6] ^ w[11]; w[14] = RL(w[14], 1);
+ D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[14]; A = RL(A, 30);
+ w[15] = w[15] ^ w[ 1] ^ w[ 7] ^ w[12]; w[15] = RL(w[15], 1);
+ C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[15]; E = RL(E, 30);
+ w[ 0] = w[ 0] ^ w[ 2] ^ w[ 8] ^ w[13]; w[ 0] = RL(w[ 0], 1);
+ B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[ 0]; D = RL(D, 30);
+ w[ 1] = w[ 1] ^ w[ 3] ^ w[ 9] ^ w[14]; w[ 1] = RL(w[ 1], 1);
+ A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[ 1]; C = RL(C, 30);
+ w[ 2] = w[ 2] ^ w[ 4] ^ w[10] ^ w[15]; w[ 2] = RL(w[ 2], 1);
+ E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[ 2]; B = RL(B, 30);
+ w[ 3] = w[ 3] ^ w[ 5] ^ w[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+ D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[ 3]; A = RL(A, 30);
+ w[ 4] = w[ 4] ^ w[ 6] ^ w[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+ C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[ 4]; E = RL(E, 30);
+ w[ 5] = w[ 5] ^ w[ 7] ^ w[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+ B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[ 5]; D = RL(D, 30);
+ w[ 6] = w[ 6] ^ w[ 8] ^ w[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+ A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[ 6]; C = RL(C, 30);
+ w[ 7] = w[ 7] ^ w[ 9] ^ w[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+ E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[ 7]; B = RL(B, 30);
+ w[ 8] = w[ 8] ^ w[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+ D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[ 8]; A = RL(A, 30);
+ w[ 9] = w[ 9] ^ w[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+ C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[ 9]; E = RL(E, 30);
+ w[10] = w[10] ^ w[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+ B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[10]; D = RL(D, 30);
+ w[11] = w[11] ^ w[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+ A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[11]; C = RL(C, 30);
+
+ /* rounds 60 - 79 */
+
+ w[12] = w[12] ^ w[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+ E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[12]; B = RL(B, 30);
+ w[13] = w[13] ^ w[15] ^ w[ 5] ^ w[10]; w[13] = RL(w[13], 1);
+ D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[13]; A = RL(A, 30);
+ w[14] = w[14] ^ w[ 0] ^ w[ 6] ^ w[11]; w[14] = RL(w[14], 1);
+ C += RL(D, 5) + K60_79 + (E ^ A ^ B) + w[14]; E = RL(E, 30);
+ w[15] = w[15] ^ w[ 1] ^ w[ 7] ^ w[12]; w[15] = RL(w[15], 1);
+ B += RL(C, 5) + K60_79 + (D ^ E ^ A) + w[15]; D = RL(D, 30);
+ w[ 0] = w[ 0] ^ w[ 2] ^ w[ 8] ^ w[13]; w[ 0] = RL(w[ 0], 1);
+ A += RL(B, 5) + K60_79 + (C ^ D ^ E) + w[ 0]; C = RL(C, 30);
+ w[ 1] = w[ 1] ^ w[ 3] ^ w[ 9] ^ w[14]; w[ 1] = RL(w[ 1], 1);
+ E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[ 1]; B = RL(B, 30);
+ w[ 2] = w[ 2] ^ w[ 4] ^ w[10] ^ w[15]; w[ 2] = RL(w[ 2], 1);
+ D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[ 2]; A = RL(A, 30);
+ w[ 3] = w[ 3] ^ w[ 5] ^ w[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+ C += RL(D, 5) + K60_79 + (E ^ A ^ B) + w[ 3]; E = RL(E, 30);
+ w[ 4] = w[ 4] ^ w[ 6] ^ w[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+ B += RL(C, 5) + K60_79 + (D ^ E ^ A) + w[ 4]; D = RL(D, 30);
+ w[ 5] = w[ 5] ^ w[ 7] ^ w[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+ A += RL(B, 5) + K60_79 + (C ^ D ^ E) + w[ 5]; C = RL(C, 30);
+ w[ 6] = w[ 6] ^ w[ 8] ^ w[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+ E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[ 6]; B = RL(B, 30);
+ w[ 7] = w[ 7] ^ w[ 9] ^ w[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+ D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[ 7]; A = RL(A, 30);
+ w[ 8] = w[ 8] ^ w[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+ C += RL(D, 5) + K60_79 + (E ^ A ^ B) + w[ 8]; E = RL(E, 30);
+ w[ 9] = w[ 9] ^ w[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+ B += RL(C, 5) + K60_79 + (D ^ E ^ A) + w[ 9]; D = RL(D, 30);
+ w[10] = w[10] ^ w[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+ A += RL(B, 5) + K60_79 + (C ^ D ^ E) + w[10]; C = RL(C, 30);
+ w[11] = w[11] ^ w[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+ E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[11]; B = RL(B, 30);
+ w[12] = w[12] ^ w[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+ D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[12]; A = RL(A, 30);
+ w[13] = w[13] ^ w[15] ^ w[ 5] ^ w[10];
+ C += RL(D, 5) + K60_79 + (E ^ A ^ B) + RL(w[13], 1); E = RL(E, 30);
+ w[14] = w[14] ^ w[ 0] ^ w[ 6] ^ w[11];
+ B += RL(C, 5) + K60_79 + (D ^ E ^ A) + RL(w[14], 1); D = RL(D, 30);
+
+ /* update H0 - H4 */
+
+ w[15] = w[15] ^ w[ 1] ^ w[ 7] ^ w[12];
+ H0 += A + RL(B, 5) + K60_79 + (C ^ D ^ E) + RL(w[15], 1);
+ H1 += B;
+ H2 += RL(C, 30);
+ H3 += D;
+ H4 += E;
+
+ /* clear temp variables */
+
+ A = B = C = D = E = 0;
+ memset(w, 0, sizeof(w));
+}
+
+
+/* ntru_crypto_sha1()
+ *
+ * This routine provides all operations for a SHA-1 hash, and the use
+ * of SHA-1 for DSA signing and key generation.
+ * It may be used to initialize, update, or complete a message digest,
+ * or any combination of those actions, as determined by the SHA_INIT flag,
+ * the in_len parameter, and the SHA_FINISH flag, respectively.
+ *
+ * When in_len == 0 (no data to hash), the parameter, in, may be NULL.
+ * When the SHA_FINISH flag is not set, the parameter, md, may be NULL.
+ *
+ * Initialization may be standard or use a specified initialization vector,
+ * and is indicated by setting the SHA_INIT flag.
+ * Setting init = NULL specifies standard initialization. Otherwise, init
+ * points to the array of five alternate initialization 32-bit words.
+ *
+ * The hash operation can be updated with any number of input bytes, including
+ * zero.
+ *
+ * The hash operation can be completed with normal padding or with zero
+ * padding as required for parts of DSA parameter generation, and is indicated
+ * by setting the SHA_FINISH flag. Using zero padding, indicated by setting
+ * the SHA_ZERO_PAD flag, never creates an extra input block because the
+ * bit count is not included in the hashed data.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint32_t const *init, /* in - pointer to alternate */
+ /* initialization - may be NULL */
+ uint8_t const *in, /* in - pointer to input data -
+ may be NULL if in_len == 0 */
+ uint32_t in_len, /* in - number of input data bytes */
+ uint32_t flags, /* in - INIT, FINISH, zero-pad flags */
+ uint8_t *md) /* out - address for message digest -
+ may be NULL if not FINISH */
+{
+ uint32_t in_blk[16]; /* input block */
+ uint32_t space;
+ uint8_t *d = NULL;
+
+ /* check error conditions */
+
+ if (!c || (in_len && !in) || ((flags & SHA_FINISH) && !md))
+ SHA_RET(SHA_BAD_PARAMETER)
+
+ /* initialize context if requested */
+
+ if (flags & SHA_INIT) {
+
+ /* init chaining state */
+
+ if (!init) {
+ c->state[0] = H0_INIT; // standard initialization
+ c->state[1] = H1_INIT;
+ c->state[2] = H2_INIT;
+ c->state[3] = H3_INIT;
+ c->state[4] = H4_INIT;
+ } else {
+ c->state[0] = init[0]; // alternate initialization
+ c->state[1] = init[1];
+ c->state[2] = init[2];
+ c->state[3] = init[3];
+ c->state[4] = init[4];
+ }
+
+ /* init bit count and number of unhashed data bytes */
+
+ c->num_bits_hashed[0] = 0;
+ c->num_bits_hashed[1] = 0;
+ c->unhashed_len = 0;
+ }
+
+ /* determine space left in unhashed data buffer */
+
+ if (c->unhashed_len > 63)
+ SHA_RET(SHA_FAIL)
+
+ space = 64 - c->unhashed_len;
+
+ /* process input if it exists */
+
+ if (in_len) {
+
+ /* update count of bits hashed */
+
+ {
+ uint32_t bits0, bits1;
+
+ bits0 = in_len << 3;
+ bits1 = in_len >> 29;
+ if ((c->num_bits_hashed[0] += bits0) < bits0)
+ bits1++;
+ if ((c->num_bits_hashed[1] += bits1) < bits1) {
+ memset((uint8_t *) c, 0, sizeof(NTRU_CRYPTO_SHA1_CTX));
+ space = 0;
+ memset((char *) in_blk, 0, sizeof(in_blk));
+ SHA_RET(SHA_OVERFLOW)
+ }
+ }
+
+ /* process input bytes */
+
+ if (in_len < space) {
+
+ /* input does not fill block buffer:
+ * add input to buffer
+ */
+
+ memcpy(c->unhashed + c->unhashed_len, in, in_len);
+ c->unhashed_len += in_len;
+
+ } else {
+ uint32_t blks;
+
+ /* input will fill block buffer:
+ * fill unhashed data buffer,
+ * convert to block buffer,
+ * and process block
+ */
+
+ in_len -= space;
+ for (d = c->unhashed + c->unhashed_len; space; space--)
+ *d++ = *in++;
+ ntru_crypto_msbyte_2_uint32(in_blk, (uint8_t const *) c->unhashed,
+ 16);
+ sha1_blk((uint32_t const *) in_blk, c->state);
+
+ /* process any remaining full blocks */
+
+ for (blks = in_len >> 6; blks--; in += 64) {
+ ntru_crypto_msbyte_2_uint32(in_blk, in, 16);
+ sha1_blk((uint32_t const *) in_blk, c->state);
+ }
+
+ /* put any remaining input in the unhashed data buffer */
+
+ in_len &= 0x3f;
+ memcpy(c->unhashed, in, in_len);
+ c->unhashed_len = in_len;
+ }
+ }
+
+ /* complete message digest if requested */
+
+ if (flags & SHA_FINISH) {
+ space = 64 - c->unhashed_len;
+
+ /* check padding type */
+
+ if (!(flags & SHA_ZERO_PAD)) {
+
+ /* add 0x80 padding byte to the unhashed data buffer
+ * (there is always space since the buffer can't be full)
+ */
+
+ d = c->unhashed + c->unhashed_len;
+ *d++ = 0x80;
+ space--;
+
+ /* check for space for bit count */
+
+ if (space < 8) {
+
+ /* no space for count:
+ * fill remainder of unhashed data buffer with zeros,
+ * convert to input block,
+ * process block,
+ * fill all but 8 bytes of unhashed data buffer with zeros
+ */
+
+ memset(d, 0, space);
+ ntru_crypto_msbyte_2_uint32(in_blk,
+ (uint8_t const *) c->unhashed, 16);
+ sha1_blk((uint32_t const *) in_blk, c->state);
+ memset(c->unhashed, 0, 56);
+
+ } else {
+
+ /* fill unhashed data buffer with zeros,
+ * leaving space for bit count
+ */
+
+ for (space -= 8; space; space--)
+ *d++ = 0;
+ }
+
+ /* convert partially filled unhashed data buffer to input block and
+ * add bit count to input block
+ */
+
+ ntru_crypto_msbyte_2_uint32(in_blk, (uint8_t const *) c->unhashed,
+ 14);
+ in_blk[14] = c->num_bits_hashed[1];
+ in_blk[15] = c->num_bits_hashed[0];
+
+ } else {
+
+ /* pad unhashed data buffer with zeros and no bit count and
+ * convert to input block
+ */
+
+ memset(c->unhashed + c->unhashed_len, 0, space);
+ ntru_crypto_msbyte_2_uint32(in_blk, (uint8_t const *) c->unhashed,
+ 16);
+ }
+
+ /* process last block */
+
+ sha1_blk((uint32_t const *) in_blk, c->state);
+
+ /* copy result to message digest buffer */
+
+ ntru_crypto_uint32_2_msbyte(md, c->state, 5);
+
+ /* clear context and stack variables */
+
+ memset((uint8_t *) c, 0, sizeof(NTRU_CRYPTO_SHA1_CTX));
+ space = 0;
+ memset((char *) in_blk, 0, sizeof(in_blk));
+ }
+
+ SHA_RET(SHA_OK)
+}
+
+
+/* ntru_crypto_sha1_init
+ *
+ * This routine performs standard initialization of the SHA-1 state.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ */
+
+uint32_t
+ntru_crypto_sha1_init(
+ NTRU_CRYPTO_SHA1_CTX *c) /* in/out - pointer to SHA-1 context */
+{
+ return ntru_crypto_sha1(c, NULL, NULL, 0, SHA_INIT, NULL);
+}
+
+
+/* ntru_crypto_sha1_update
+ *
+ * This routine processes input data and updates the SHA-1 hash calculation.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_update(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint8_t const *data, /* in - pointer to input data */
+ uint32_t data_len) /* in - number of bytes of input data */
+{
+ return ntru_crypto_sha1(c, NULL, data, data_len, SHA_DATA_ONLY, NULL);
+}
+
+
+/* ntru_crypto_sha1_final
+ *
+ * This routine completes the SHA-1 hash calculation and returns the
+ * message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_final(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint8_t *md) /* out - address for message digest */
+{
+ return ntru_crypto_sha1(c, NULL, NULL, 0, SHA_FINISH, md);
+}
+
+
+/* ntru_crypto_sha1_final_zero_pad
+ *
+ * This routine completes the SHA-1 hash calculation using zero padding
+ * and returns the message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_final_zero_pad(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint8_t *md) /* out - address for message digest */
+{
+ return ntru_crypto_sha1(c, NULL, NULL, 0, SHA_FINISH | SHA_ZERO_PAD, md);
+}
+
+
+/* ntru_crypto_sha1_digest
+ *
+ * This routine computes a SHA-1 message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_digest(
+ uint8_t const *data, // in - pointer to input data
+ uint32_t data_len, // in - number of bytes of input data
+ uint8_t *md) // out - address for message digest
+{
+ NTRU_CRYPTO_SHA1_CTX c;
+
+ return ntru_crypto_sha1(&c, NULL, data, data_len, SHA_INIT | SHA_FINISH,
+ md);
+}
+
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_crypto_sha1.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_sha1.h
+ *
+ * Contents: Definitions and declarations for the SHA-1 implementation.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_SHA1_H
+#define NTRU_CRYPTO_SHA1_H
+
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_sha.h"
+
+
+/******************************************
+ * macros needed for generic hash objects *
+ ******************************************/
+
+#define SHA_1_CTX_LEN sizeof(SHA1_CTX) /* no. bytes in SHA-1
+ ctx */
+#define SHA_1_BLK_LEN 64 /* 64 bytes in input
+ block */
+#define SHA_1_MD_LEN 20 /* 20 bytes in msg
+ digest */
+#define SHA_1_INIT_FN &ntru_crypto_sha1_init /* init function */
+#define SHA_1_UPDATE_FN &ntru_crypto_sha1_update /* update function */
+#define SHA_1_FINAL_FN &ntru_crypto_sha1_final /* final function */
+#define SHA_1_FINAL_ZERO_PAD_FN \
+ &ntru_crypto_sha1_final_zero_pad
+ /* final function using
+ zero padding */
+#define SHA_1_DIGEST_FN &ntru_crypto_sha1_digest /* digest function */
+
+
+/*************************
+ * structure definitions *
+ *************************/
+
+/* SHA-1 context structure */
+
+typedef struct {
+ uint32_t state[5]; // chaining state
+ uint32_t num_bits_hashed[2]; // number of bits hashed
+ uint8_t unhashed[64]; // input data not yet hashed
+ uint32_t unhashed_len; // number of bytes of unhashed input data
+} NTRU_CRYPTO_SHA1_CTX;
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_sha1()
+ *
+ * This routine provides all operations for a SHA-1 hash, and the use
+ * of SHA-1 for DSA signing and key generation.
+ * It may be used to initialize, update, or complete a message digest,
+ * or any combination of those actions, as determined by the SHA_INIT flag,
+ * the in_len parameter, and the SHA_FINISH flag, respectively.
+ *
+ * When in_len == 0 (no data to hash), the parameter, in, may be NULL.
+ * When the SHA_FINISH flag is not set, the parameter, md, may be NULL.
+ *
+ * Initialization may be standard or use a specified initialization vector,
+ * and is indicated by setting the SHA_INIT flag.
+ * Setting init = NULL specifies standard initialization. Otherwise, init
+ * points to the array of five alternate initialization 32-bit words.
+ *
+ * The hash operation can be updated with any number of input bytes, including
+ * zero.
+ *
+ * The hash operation can be completed with normal padding or with zero
+ * padding as required for parts of DSA parameter generation, and is indicated
+ * by setting the SHA_FINISH flag. Using zero padding, indicated by setting
+ * the SHA_ZERO_PAD flag, never creates an extra input block because the
+ * bit count is not included in the hashed data.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint32_t const *init, /* in - pointer to alternate */
+ /* initialization - may be NULL */
+ uint8_t const *in, /* in - pointer to input data -
+ may be NULL if in_len == 0 */
+ uint32_t in_len, /* in - number of input data bytes */
+ uint32_t flags, /* in - INIT, FINISH, zero-pad flags */
+ uint8_t *md); /* out - address for message digest -
+ may be NULL if not FINISH */
+
+
+/* ntru_crypto_sha1_init
+ *
+ * This routine performs standard initialization of the SHA-1 state.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_init(
+ NTRU_CRYPTO_SHA1_CTX *c); /* in/out - pointer to SHA-1 context */
+
+
+/* ntru_crypto_sha1_update
+ *
+ * This routine processes input data and updates the SHA-1 hash calculation.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_update(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint8_t const *data, /* in - pointer to input data */
+ uint32_t data_len); /* in - number of bytes of input data */
+
+
+/* ntru_crypto_sha1_final
+ *
+ * This routine completes the SHA-1 hash calculation and returns the
+ * message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_final(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint8_t *md); /* out - address for message digest */
+
+
+/* ntru_crypto_sha1_final_zero_pad
+ *
+ * This routine completes the SHA-1 hash calculation using zero padding
+ * and returns the message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_final_zero_pad(
+ NTRU_CRYPTO_SHA1_CTX *c, /* in/out - pointer to SHA-1 context */
+ uint8_t *md); /* out - address for message digest */
+
+
+/* ntru_crypto_sha1_digest
+ *
+ * This routine computes a SHA-1 message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_digest(
+ uint8_t const *data, /* in - pointer to input data */
+ uint32_t data_len, /* in - number of bytes of input data */
+ uint8_t *md); /* out - address for message digest */
+
+
+#endif /* NTRU_CRYPTO_SHA1_H */
--- /dev/null
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
+ *
+ * ntru_crypto_sha2.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_sha2.c
+ *
+ * Contents: Routines implementing the SHA-256 hash calculation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_sha2.h"
+#include "ntru_crypto_msbyte_uint32.h"
+
+
+/* chaining state elements */
+
+#define H0 state[0]
+#define H1 state[1]
+#define H2 state[2]
+#define H3 state[3]
+#define H4 state[4]
+#define H5 state[5]
+#define H6 state[6]
+#define H7 state[7]
+
+
+/* standard SHA-256 initialization values */
+
+#define H0_SHA256_INIT 0x6a09e667UL
+#define H1_SHA256_INIT 0xbb67ae85UL
+#define H2_SHA256_INIT 0x