Prototype implementation of IKE key exchange via NTRU encryption

This commit is contained in:
Andreas Steffen 2013-11-18 21:11:03 +01:00
parent e9b49d412b
commit 146ad86be5
42 changed files with 9386 additions and 4 deletions

View File

@ -239,6 +239,7 @@ ARG_ENABL_SET([pkcs11], [enables the PKCS11 token support plugin.])
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.])
@ -1033,6 +1034,7 @@ ADD_PLUGIN([hmac], [s charon scripts nm cmd])
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])
@ -1170,6 +1172,7 @@ AM_CONDITIONAL(USE_CTR, test x$ctr = xtrue)
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
# ----------------
@ -1375,6 +1378,7 @@ AC_CONFIG_FILES([
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

View File

@ -481,6 +481,13 @@ if MONOLITHIC
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

View File

@ -93,6 +93,7 @@
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
@ -211,6 +212,29 @@
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"

View File

@ -45,7 +45,12 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_1024_160, ECP_512_BP, ECP_521_BIT,
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);
/**

View File

@ -64,6 +64,11 @@ enum diffie_hellman_group_t {
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
};
/**

View File

@ -1,7 +1,7 @@
%{
/*
* 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
@ -161,5 +161,9 @@ ecp224bp, DIFFIE_HELLMAN_GROUP, ECP_224_BP, 0
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

View File

@ -0,0 +1,39 @@
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

View File

@ -0,0 +1,337 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,724 @@
/******************************************************************************
* 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);
}

View File

@ -0,0 +1,193 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,47 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,335 @@
/******************************************************************************
* 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);
}

View File

@ -0,0 +1,233 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,75 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,320 @@
/******************************************************************************
* 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;
}

View File

@ -0,0 +1,183 @@
/*/******************************************************************************
* 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 */

View File

@ -0,0 +1,92 @@
/******************************************************************************
* 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] );
}
}

View File

@ -0,0 +1,75 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,581 @@
/******************************************************************************
* 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;
}
}

View File

@ -0,0 +1,183 @@
/******************************************************************************
* 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 */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
/******************************************************************************
* 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;
}
}

View File

@ -0,0 +1,167 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,457 @@
/******************************************************************************
* 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;
}

View File

@ -0,0 +1,124 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,197 @@
/******************************************************************************
* 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);
}

View File

@ -0,0 +1,98 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,586 @@
/******************************************************************************
* 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;
}

View File

@ -0,0 +1,211 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,39 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,65 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,588 @@
/******************************************************************************
* 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);
}

View File

@ -0,0 +1,205 @@
/******************************************************************************
* 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 */

View File

@ -0,0 +1,532 @@
/******************************************************************************
* 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 0x3c6ef372UL
#define H3_SHA256_INIT 0xa54ff53aUL
#define H4_SHA256_INIT 0x510e527fUL
#define H5_SHA256_INIT 0x9b05688cUL
#define H6_SHA256_INIT 0x1f83d9abUL
#define H7_SHA256_INIT 0x5be0cd19UL
/* sha2_blk()
*
* This routine updates the current hash output (chaining state)
* by performing SHA-256 on a 512-bit block of data represented
* as sixteen 32-bit words.
*/
#define RR(a, n) ( ((a) >> (n)) | ((a) << (32 - (n))) )
#define S0(a) ( RR((a), 2) ^ RR((a), 13) ^ RR((a), 22) )
#define S1(a) ( RR((a), 6) ^ RR((a), 11) ^ RR((a), 25) )
#define s0(a) ( RR((a), 7) ^ RR((a), 18) ^ ((a) >> 3) )
#define s1(a) ( RR((a), 17) ^ RR((a), 19) ^ ((a) >> 10) )
static void
sha2_blk(
uint32_t const *data, // in - ptr to 16 32-bit word input block
uint32_t *state) // in/out - ptr to 8 32-bit word chaining state
{
uint32_t A, B, C, D, E, F, G, H;
uint32_t w[16];
/* init A - H */
A = H0; B = H1; C = H2; D = H3; E = H4; F = H5; G = H6; H = H7;
/* rounds 0 - 15 */
H += S1(E) + (E & (F ^ G) ^ G) + 0x428A2F98UL + data[ 0]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
G += S1(D) + (D & (E ^ F) ^ F) + 0x71374491UL + data[ 1]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
F += S1(C) + (C & (D ^ E) ^ E) + 0xB5C0FBCFUL + data[ 2]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
E += S1(B) + (B & (C ^ D) ^ D) + 0xE9B5DBA5UL + data[ 3]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
D += S1(A) + (A & (B ^ C) ^ C) + 0x3956C25BUL + data[ 4]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
C += S1(H) + (H & (A ^ B) ^ B) + 0x59F111F1UL + data[ 5]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
B += S1(G) + (G & (H ^ A) ^ A) + 0x923F82A4UL + data[ 6]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
A += S1(F) + (F & (G ^ H) ^ H) + 0xAB1C5ED5UL + data[ 7]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
H += S1(E) + (E & (F ^ G) ^ G) + 0xD807AA98UL + data[ 8]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
G += S1(D) + (D & (E ^ F) ^ F) + 0x12835B01UL + data[ 9]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
F += S1(C) + (C & (D ^ E) ^ E) + 0x243185BEUL + data[10]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
E += S1(B) + (B & (C ^ D) ^ D) + 0x550C7DC3UL + data[11]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
D += S1(A) + (A & (B ^ C) ^ C) + 0x72BE5D74UL + data[12]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
C += S1(H) + (H & (A ^ B) ^ B) + 0x80DEB1FEUL + data[13]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
B += S1(G) + (G & (H ^ A) ^ A) + 0x9BDC06A7UL + data[14]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
A += S1(F) + (F & (G ^ H) ^ H) + 0xC19BF174UL + data[15]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
/* rounds 16 - 63 */
w[ 0] = data[ 0] + s0(data[ 1]) + data[ 9] + s1(data[14]);
H += S1(E) + (E & (F ^ G) ^ G) + 0xE49B69C1UL + w[ 0]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
w[ 1] = data[ 1] + s0(data[ 2]) + data[10] + s1(data[15]);
G += S1(D) + (D & (E ^ F) ^ F) + 0xEFBE4786UL + w[ 1]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
w[ 2] = data[ 2] + s0(data[ 3]) + data[11] + s1(w[ 0]);
F += S1(C) + (C & (D ^ E) ^ E) + 0x0FC19DC6UL + w[ 2]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
w[ 3] = data[ 3] + s0(data[ 4]) + data[12] + s1(w[ 1]);
E += S1(B) + (B & (C ^ D) ^ D) + 0x240CA1CCUL + w[ 3]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
w[ 4] = data[ 4] + s0(data[ 5]) + data[13] + s1(w[ 2]);
D += S1(A) + (A & (B ^ C) ^ C) + 0x2DE92C6FUL + w[ 4]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
w[ 5] = data[ 5] + s0(data[ 6]) + data[14] + s1(w[ 3]);
C += S1(H) + (H & (A ^ B) ^ B) + 0x4A7484AAUL + w[ 5]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
w[ 6] = data[ 6] + s0(data[ 7]) + data[15] + s1(w[ 4]);
B += S1(G) + (G & (H ^ A) ^ A) + 0x5CB0A9DCUL + w[ 6]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
w[ 7] = data[ 7] + s0(data[ 8]) + w[ 0] + s1(w[ 5]);
A += S1(F) + (F & (G ^ H) ^ H) + 0x76F988DAUL + w[ 7]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
w[ 8] = data[ 8] + s0(data[ 9]) + w[ 1] + s1(w[ 6]);
H += S1(E) + (E & (F ^ G) ^ G) + 0x983E5152UL + w[ 8]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
w[ 9] = data[ 9] + s0(data[10]) + w[ 2] + s1(w[ 7]);
G += S1(D) + (D & (E ^ F) ^ F) + 0xA831C66DUL + w[ 9]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
w[10] = data[10] + s0(data[11]) + w[ 3] + s1(w[ 8]);
F += S1(C) + (C & (D ^ E) ^ E) + 0xB00327C8UL + w[10]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
w[11] = data[11] + s0(data[12]) + w[ 4] + s1(w[ 9]);
E += S1(B) + (B & (C ^ D) ^ D) + 0xBF597FC7UL + w[11]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
w[12] = data[12] + s0(data[13]) + w[ 5] + s1(w[10]);
D += S1(A) + (A & (B ^ C) ^ C) + 0xC6E00BF3UL + w[12]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
w[13] = data[13] + s0(data[14]) + w[ 6] + s1(w[11]);
C += S1(H) + (H & (A ^ B) ^ B) + 0xD5A79147UL + w[13]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
w[14] = data[14] + s0(data[15]) + w[ 7] + s1(w[12]);
B += S1(G) + (G & (H ^ A) ^ A) + 0x06CA6351UL + w[14]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
w[15] = data[15] + s0(w[ 0]) + w[ 8] + s1(w[13]);
A += S1(F) + (F & (G ^ H) ^ H) + 0x14292967UL + w[15]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
w[ 0] = w[ 0] + s0(w[ 1]) + w[ 9] + s1(w[14]);
H += S1(E) + (E & (F ^ G) ^ G) + 0x27B70A85UL + w[ 0]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
w[ 1] = w[ 1] + s0(w[ 2]) + w[10] + s1(w[15]);
G += S1(D) + (D & (E ^ F) ^ F) + 0x2E1B2138UL + w[ 1]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
w[ 2] = w[ 2] + s0(w[ 3]) + w[11] + s1(w[ 0]);
F += S1(C) + (C & (D ^ E) ^ E) + 0x4D2C6DFCUL + w[ 2]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
w[ 3] = w[ 3] + s0(w[ 4]) + w[12] + s1(w[ 1]);
E += S1(B) + (B & (C ^ D) ^ D) + 0x53380D13UL + w[ 3]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
w[ 4] = w[ 4] + s0(w[ 5]) + w[13] + s1(w[ 2]);
D += S1(A) + (A & (B ^ C) ^ C) + 0x650A7354UL + w[ 4]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
w[ 5] = w[ 5] + s0(w[ 6]) + w[14] + s1(w[ 3]);
C += S1(H) + (H & (A ^ B) ^ B) + 0x766A0ABBUL + w[ 5]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
w[ 6] = w[ 6] + s0(w[ 7]) + w[15] + s1(w[ 4]);
B += S1(G) + (G & (H ^ A) ^ A) + 0x81C2C92EUL + w[ 6]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
w[ 7] = w[ 7] + s0(w[ 8]) + w[ 0] + s1(w[ 5]);
A += S1(F) + (F & (G ^ H) ^ H) + 0x92722C85UL + w[ 7]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
w[ 8] = w[ 8] + s0(w[ 9]) + w[ 1] + s1(w[ 6]);
H += S1(E) + (E & (F ^ G) ^ G) + 0xA2BFE8A1UL + w[ 8]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
w[ 9] = w[ 9] + s0(w[10]) + w[ 2] + s1(w[ 7]);
G += S1(D) + (D & (E ^ F) ^ F) + 0xA81A664BUL + w[ 9]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
w[10] = w[10] + s0(w[11]) + w[ 3] + s1(w[ 8]);
F += S1(C) + (C & (D ^ E) ^ E) + 0xC24B8B70UL + w[10]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
w[11] = w[11] + s0(w[12]) + w[ 4] + s1(w[ 9]);
E += S1(B) + (B & (C ^ D) ^ D) + 0xC76C51A3UL + w[11]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
w[12] = w[12] + s0(w[13]) + w[ 5] + s1(w[10]);
D += S1(A) + (A & (B ^ C) ^ C) + 0xD192E819UL + w[12]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
w[13] = w[13] + s0(w[14]) + w[ 6] + s1(w[11]);
C += S1(H) + (H & (A ^ B) ^ B) + 0xD6990624UL + w[13]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
w[14] = w[14] + s0(w[15]) + w[ 7] + s1(w[12]);
B += S1(G) + (G & (H ^ A) ^ A) + 0xF40E3585UL + w[14]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
w[15] = w[15] + s0(w[ 0]) + w[ 8] + s1(w[13]);
A += S1(F) + (F & (G ^ H) ^ H) + 0x106AA070UL + w[15]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
w[ 0] = w[ 0] + s0(w[ 1]) + w[ 9] + s1(w[14]);
H += S1(E) + (E & (F ^ G) ^ G) + 0x19A4C116UL + w[ 0]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
w[ 1] = w[ 1] + s0(w[ 2]) + w[10] + s1(w[15]);
G += S1(D) + (D & (E ^ F) ^ F) + 0x1E376C08UL + w[ 1]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
w[ 2] = w[ 2] + s0(w[ 3]) + w[11] + s1(w[ 0]);
F += S1(C) + (C & (D ^ E) ^ E) + 0x2748774CUL + w[ 2]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
w[ 3] = w[ 3] + s0(w[ 4]) + w[12] + s1(w[ 1]);
E += S1(B) + (B & (C ^ D) ^ D) + 0x34B0BCB5UL + w[ 3]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
w[ 4] = w[ 4] + s0(w[ 5]) + w[13] + s1(w[ 2]);
D += S1(A) + (A & (B ^ C) ^ C) + 0x391C0CB3UL + w[ 4]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
w[ 5] = w[ 5] + s0(w[ 6]) + w[14] + s1(w[ 3]);
C += S1(H) + (H & (A ^ B) ^ B) + 0x4ED8AA4AUL + w[ 5]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
w[ 6] = w[ 6] + s0(w[ 7]) + w[15] + s1(w[ 4]);
B += S1(G) + (G & (H ^ A) ^ A) + 0x5B9CCA4FUL + w[ 6]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
w[ 7] = w[ 7] + s0(w[ 8]) + w[ 0] + s1(w[ 5]);
A += S1(F) + (F & (G ^ H) ^ H) + 0x682E6FF3UL + w[ 7]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
w[ 8] = w[ 8] + s0(w[ 9]) + w[ 1] + s1(w[ 6]);
H += S1(E) + (E & (F ^ G) ^ G) + 0x748F82EEUL + w[ 8]; D += H;
H += S0(A) + ((A & B) | (C & (A | B)));
w[ 9] = w[ 9] + s0(w[10]) + w[ 2] + s1(w[ 7]);
G += S1(D) + (D & (E ^ F) ^ F) + 0x78A5636FUL + w[ 9]; C += G;
G += S0(H) + ((H & A) | (B & (H | A)));
w[10] = w[10] + s0(w[11]) + w[ 3] + s1(w[ 8]);
F += S1(C) + (C & (D ^ E) ^ E) + 0x84C87814UL + w[10]; B += F;
F += S0(G) + ((G & H) | (A & (G | H)));
w[11] = w[11] + s0(w[12]) + w[ 4] + s1(w[ 9]);
E += S1(B) + (B & (C ^ D) ^ D) + 0x8CC70208UL + w[11]; A += E;
E += S0(F) + ((F & G) | (H & (F | G)));
w[12] = w[12] + s0(w[13]) + w[ 5] + s1(w[10]);
D += S1(A) + (A & (B ^ C) ^ C) + 0x90BEFFFAUL + w[12]; H += D;
D += S0(E) + ((E & F) | (G & (E | F)));
w[13] = w[13] + s0(w[14]) + w[ 6] + s1(w[11]);
C += S1(H) + (H & (A ^ B) ^ B) + 0xA4506CEBUL + w[13]; G += C;
C += S0(D) + ((D & E) | (F & (D | E)));
w[14] = w[14] + s0(w[15]) + w[ 7] + s1(w[12]);
B += S1(G) + (G & (H ^ A) ^ A) + 0xBEF9A3F7UL + w[14]; F += B;
B += S0(C) + ((C & D) | (E & (C | D)));
w[15] = w[15] + s0(w[ 0]) + w[ 8] + s1(w[13]);
A += S1(F) + (F & (G ^ H) ^ H) + 0xC67178F2UL + w[15]; E += A;
A += S0(B) + ((B & C) | (D & (B | C)));
/* update H0 - H7 */
H0 += A;
H1 += B;
H2 += C;
H3 += D;
H4 += E;
H5 += F;
H6 += G;
H7 += H;
/* clear temp variables */
A = B = C = D = E = F = G = H = 0;
memset(w, 0, sizeof(w));
}
/* ntru_crypto_sha2()
*
* This routine provides all operations for a SHA-256 hash,
* and the use of SHA-256 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 eight 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_sha2(
NTRU_CRYPTO_HASH_ALGID algid, // in - hash algorithm ID
NTRU_CRYPTO_SHA2_CTX *c, // in/out - pointer to SHA-2 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 (algid != NTRU_CRYPTO_HASH_ALGID_SHA256)
SHA_RET(SHA_BAD_PARAMETER)
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) { // standard initialization
c->state[0] = H0_SHA256_INIT; // standard SHA-256 init
c->state[1] = H1_SHA256_INIT;
c->state[2] = H2_SHA256_INIT;
c->state[3] = H3_SHA256_INIT;
c->state[4] = H4_SHA256_INIT;
c->state[5] = H5_SHA256_INIT;
c->state[6] = H6_SHA256_INIT;
c->state[7] = H7_SHA256_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];
c->state[5] = init[5];
c->state[6] = init[6];
c->state[7] = init[7];
}
/* 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_SHA2_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);
sha2_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);
sha2_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);
sha2_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 */
sha2_blk((uint32_t const *) in_blk, c->state);
/* copy result to message digest buffer */
ntru_crypto_uint32_2_msbyte(md, c->state, 8);
/* clear context and stack variables */
memset((uint8_t *) c, 0, sizeof(NTRU_CRYPTO_SHA2_CTX));
space = 0;
memset((char *) in_blk, 0, sizeof(in_blk));
}
SHA_RET(SHA_OK)
}

View File

@ -0,0 +1,104 @@
/******************************************************************************
* NTRU Cryptography Reference Source Code
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
*
* ntru_crypto_crypto_sha2.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_sha2.h
*
* Contents: Definitions and declarations for the SHA-256 implementation.
*
*****************************************************************************/
#ifndef NTRU_CRYPTO_SHA2_H
#define NTRU_CRYPTO_SHA2_H
#include "ntru_crypto_platform.h"
#include "ntru_crypto_sha.h"
/*************************
* structure definitions *
*************************/
/* SHA-256 context structure */
typedef struct {
uint32_t state[8]; /* 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_SHA2_CTX;
/*************************
* function declarations *
*************************/
/* ntru_crypto_sha2()
*
* This routine provides all operations for a SHA-256 hash,
* and the use of SHA-256 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 eight 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_sha2(
NTRU_CRYPTO_HASH_ALGID algid, /* in - hash algorithm ID */
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 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 */
#endif /* NTRU_CRYPTO_SHA2_H */

View File

@ -0,0 +1,140 @@
/******************************************************************************
* NTRU Cryptography Reference Source Code
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
*
* ntru_crypto_sha256.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_sha256.c
*
* Contents: Routines implementing the SHA-256 hash calculations.
*
*****************************************************************************/
#include <stdlib.h>
#include "ntru_crypto_sha256.h"
/* ntru_crypto_sha256_init
*
* This routine performs standard initialization of the SHA-256 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_sha256_init(
NTRU_CRYPTO_SHA2_CTX *c) /* in/out - pointer to SHA-2 context */
{
return ntru_crypto_sha2(NTRU_CRYPTO_HASH_ALGID_SHA256, c, NULL, NULL, 0,
SHA_INIT, NULL);
}
/* ntru_crypto_sha256_update
*
* This routine processes input data and updates the SHA-256 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_sha256_update(
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 context */
uint8_t const *data, /* in - pointer to input data */
uint32_t data_len) /* in - no. of bytes of input data */
{
return ntru_crypto_sha2(NTRU_CRYPTO_HASH_ALGID_SHA256, c, NULL, data,
data_len, SHA_DATA_ONLY, NULL);
}
/* ntru_crypto_sha256_final
*
* This routine completes the SHA-256 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_sha256_final(
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 context */
uint8_t *md) /* out - address for message digest */
{
return ntru_crypto_sha2(NTRU_CRYPTO_HASH_ALGID_SHA256, c, NULL, NULL, 0,
SHA_FINISH, md);
}
/* ntru_crypto_sha256_final_zero_pad
*
* This routine completes the SHA-256 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_sha256_final_zero_pad(
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 context */
uint8_t *md) /* out - address for message digest */
{
return ntru_crypto_sha2(NTRU_CRYPTO_HASH_ALGID_SHA256, c, NULL, NULL, 0,
SHA_FINISH | SHA_ZERO_PAD, md);
}
/* ntru_crypto_sha256_digest
*
* This routine computes a SHA-256 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_sha256_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_SHA2_CTX c;
return ntru_crypto_sha2(NTRU_CRYPTO_HASH_ALGID_SHA256, &c, NULL, data,
data_len, SHA_INIT | SHA_FINISH, md);
}

View File

@ -0,0 +1,149 @@
/******************************************************************************
* NTRU Cryptography Reference Source Code
* Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
*
* ntru_crypto_sha256.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_sha256.h
*
* Contents: Definitions and declarations for the SHA-256 implementation.
*
*****************************************************************************/
#ifndef CRYPTO_SHA256_H
#define CRYPTO_SHA256_H
#include "ntru_crypto_platform.h"
#include "ntru_crypto_sha2.h"
/******************************************
* macros needed for generic hash objects *
******************************************/
#define SHA_256_CTX_LEN sizeof(NTRU_CRYPTO_SHA2_CTX)
/* no. bytes in SHA-2
ctx */
#define SHA_256_BLK_LEN 64 /* 64 bytes in input
block */
#define SHA_256_MD_LEN 32 /* 32 bytes in msg
digest */
#define SHA_256_INIT_FN &ntru_crypto_sha256_init /* init function */
#define SHA_256_UPDATE_FN &ntru_crypto_sha256_update /* update function */
#define SHA_256_FINAL_FN &ntru_crypto_sha256_final /* final function */
#define SHA_256_FINAL_ZERO_PAD_FN \
&ntru_crypto_sha256_final_zero_pad
/* final function using
zero padding */
#define SHA_256_DIGEST_FN &ntru_crypto_sha256_digest /* digest function */
/*************************
* function declarations *
*************************/
/* ntru_crypto_sha256_init
*
* This routine performs standard initialization of the SHA-256 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_sha256_init(
NTRU_CRYPTO_SHA2_CTX *c); /* in/out - pointer to SHA-2 context */
/* ntru_crypto_sha256_update
*
* This routine processes input data and updates the SHA-256 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_sha256_update(
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 context */
uint8_t const *data, /* in - pointer to input data */
uint32_t data_len); /* in - no. of bytes of input data */
/* ntru_crypto_sha256_final
*
* This routine completes the SHA-256 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_sha256_final(
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 context */
uint8_t *md); /* out - address for message digest */
/* ntru_crypto_sha256_final_zero_pad
*
* This routine completes the SHA-256 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_sha256_final_zero_pad(
NTRU_CRYPTO_SHA2_CTX *c, /* in/out - pointer to SHA-2 context */
uint8_t *md); /* out - address for message digest */
/* ntru_crypto_sha256_digest
*
* This routine computes a SHA-256 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_sha256_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 /* CRYPTO_SHA256_H */

View File

@ -0,0 +1,314 @@
/*
* Copyright (C) 2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "ntru_ke.h"
#include "ntru_plugin.h"
#include "ntru_crypto/ntru_crypto.h"
#include <crypto/diffie_hellman.h>
#include <utils/debug.h>
typedef struct private_ntru_ke_t private_ntru_ke_t;
/**
* Private data of an ntru_ke_t object.
*/
struct private_ntru_ke_t {
/**
* Public ntru_ke_t interface.
*/
ntru_ke_t public;
/**
* Diffie Hellman group number.
*/
u_int16_t group;
/**
* NTRU Parameter Set ID
*/
NTRU_ENCRYPT_PARAM_SET_ID param_set_id;
/**
* Cryptographical strength in bits of the NTRU Parameter Set
*/
u_int32_t strength;
/**
* NTRU Public Key
*/
chunk_t pub_key;
/**
* NTRU Private Key
*/
chunk_t priv_key;
/**
* NTRU encrypted shared secret
*/
chunk_t ciphertext;
/**
* Shared secret
*/
chunk_t shared_secret;
/**
* True if peer is responder
*/
bool responder;
/**
* True if shared secret is computed
*/
bool computed;
/**
* Deterministic Random Bit Generator
*/
DRBG_HANDLE drbg;
};
METHOD(diffie_hellman_t, get_my_public_value, void,
private_ntru_ke_t *this, chunk_t *value)
{
uint16_t pub_key_len, priv_key_len;
*value = chunk_empty;
if (this->responder)
{
if (this->ciphertext.len)
{
*value = chunk_clone(this->ciphertext);
}
}
else
{
if (this->pub_key.len == 0)
{
/* determine the NTRU public and private key sizes */
if (ntru_crypto_ntru_encrypt_keygen(this->drbg, this->param_set_id,
&pub_key_len, NULL,
&priv_key_len, NULL) != NTRU_OK)
{
DBG1(DBG_LIB, "error determining NTRU public and private key "
"sizes");
return;
}
this->pub_key = chunk_alloc(pub_key_len);
this->priv_key = chunk_alloc(priv_key_len);
/* generate a random NTRU public/private key pair */
if (ntru_crypto_ntru_encrypt_keygen(this->drbg, this->param_set_id,
&pub_key_len, this->pub_key.ptr,
&priv_key_len, this->priv_key.ptr) != NTRU_OK)
{
DBG1(DBG_LIB, "NTRU keypair generation failed");
chunk_free(&this->priv_key);
chunk_free(&this->pub_key);
return;
}
DBG3(DBG_LIB, "NTRU public key: %B", &this->pub_key);
DBG4(DBG_LIB, "NTRU private key: %B", &this->priv_key);
}
*value = chunk_clone(this->pub_key);
}
}
METHOD(diffie_hellman_t, get_shared_secret, status_t,
private_ntru_ke_t *this, chunk_t *secret)
{
if (!this->computed || !this->shared_secret.len)
{
return FAILED;
}
*secret = chunk_clone(this->shared_secret);
return SUCCESS;
}
METHOD(diffie_hellman_t, set_other_public_value, void,
private_ntru_ke_t *this, chunk_t value)
{
u_int16_t plaintext_len, ciphertext_len;
if (this->priv_key.len)
{
/* initiator decrypting shared secret */
this->ciphertext = chunk_clone(value);
DBG3(DBG_LIB, "NTRU ciphertext: %B", &this->ciphertext);
/* determine the size of the maximum plaintext */
if (ntru_crypto_ntru_decrypt(this->priv_key.len, this->priv_key.ptr,
this->ciphertext.len, this->ciphertext.ptr,
&plaintext_len, NULL) != NTRU_OK)
{
DBG1(DBG_LIB, "error determining maximum plaintext size");
return;
}
this->shared_secret = chunk_alloc(plaintext_len);
/* decrypt the shared secret */
if (ntru_crypto_ntru_decrypt(this->priv_key.len, this->priv_key.ptr,
this->ciphertext.len, this->ciphertext.ptr,
&plaintext_len, this->shared_secret.ptr) != NTRU_OK)
{
DBG1(DBG_LIB, "NTRU decryption of shared secret failed");
chunk_free(&this->shared_secret);
return;
}
this->shared_secret.len = plaintext_len;
this->computed = TRUE;
}
else
{
/* responder generating and encrypting the shared secret */
this->responder = TRUE;
this->pub_key = chunk_clone(value);
/* shared secret size is chosen as twice the cryptographical strength */
this->shared_secret = chunk_alloc(2 * this->strength / BITS_PER_BYTE);
/* generate the random shared secret */
if (ntru_crypto_drbg_generate(this->drbg, this->strength,
this->shared_secret.len, this->shared_secret.ptr) != DRBG_OK)
{
DBG1(DBG_LIB, "generation of shared secret failed");
chunk_free(&this->shared_secret);
return;
}
/* determine the size of the ciphertext */
if (ntru_crypto_ntru_encrypt(this->drbg,
this->pub_key.len, this->pub_key.ptr,
this->shared_secret.len, this->shared_secret.ptr,
&ciphertext_len, NULL) != NTRU_OK)
{
DBG1(DBG_LIB, "error determining ciphertext size");
return;
}
this->ciphertext = chunk_alloc(ciphertext_len);
this->computed = TRUE;
/* encrypt the shared secret */
if (ntru_crypto_ntru_encrypt(this->drbg,
this->pub_key.len, this->pub_key.ptr,
this->shared_secret.len, this->shared_secret.ptr,
&ciphertext_len, this->ciphertext.ptr) != NTRU_OK)
{
DBG1(DBG_LIB, "NTRU encryption of shared secret failed");
chunk_free(&this->ciphertext);
return;
}
DBG3(DBG_LIB, "NTRU ciphertext: %B", &this->ciphertext);
}
}
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
private_ntru_ke_t *this)
{
return this->group;
}
METHOD(diffie_hellman_t, destroy, void,
private_ntru_ke_t *this)
{
if (ntru_crypto_drbg_uninstantiate(this->drbg) != DRBG_OK)
{
DBG1(DBG_LIB, "error uninstantiating DRBG");
}
chunk_free(&this->pub_key);
chunk_free(&this->ciphertext);
chunk_clear(&this->priv_key);
chunk_clear(&this->shared_secret);
free(this);
}
/*
* Described in header.
*/
ntru_ke_t *ntru_ke_create(diffie_hellman_group_t group, chunk_t g, chunk_t p)
{
private_ntru_ke_t *this;
char personalization_str[] = "strongSwan NTRU-KE";
NTRU_ENCRYPT_PARAM_SET_ID param_set_id;
DRBG_HANDLE drbg;
u_int32_t strength;
/**
* We are selecting the X9.98 / IEEE 1363.1 parameter sets
* which balance speed and bandwidth
*/
switch (group)
{
case NTRU_112_BIT:
strength = 112;
/* param_set_id = NTRU_EES541EP1; */
param_set_id = NTRU_EES401EP2;
break;
case NTRU_128_BIT:
strength = 128;
/* param_set_id = NTRU_EES613EP1; */
param_set_id = NTRU_EES439EP1;
break;
case NTRU_192_BIT:
strength = 192;
/* param_set_id = NTRU_EES887EP1; */
param_set_id = NTRU_EES593EP1;
break;
case NTRU_256_BIT:
strength = 256;
/* param_set_id = NTRU_EES1171EP1; */
param_set_id = NTRU_EES743EP1;
break;
default:
return NULL;
}
if (ntru_crypto_drbg_instantiate(strength,
personalization_str, strlen(personalization_str),
(ENTROPY_FN) &ntru_plugin_get_entropy, &drbg) != DRBG_OK)
{
DBG1(DBG_LIB, "error instantiating DRBG at %u bit security", strength);
return NULL;
}
else
{
DBG2(DBG_LIB, "instantiated DRBG at %u bit security", strength);
}
INIT(this,
.public = {
.dh = {
.get_shared_secret = _get_shared_secret,
.set_other_public_value = _set_other_public_value,
.get_my_public_value = _get_my_public_value,
.get_dh_group = _get_dh_group,
.destroy = _destroy,
},
},
.group = group,
.param_set_id = param_set_id,
.strength = strength,
.drbg = drbg,
);
return &this->public;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup ntru_ke ntru_ke
* @{ @ingroup ntru_p
*/
#ifndef NTRU_KE_H_
#define NTRU_KE_H_
typedef struct ntru_ke_t ntru_ke_t;
#include <library.h>
/**
* Implementation of a key exchange algorithm using NTRU encryption
*/
struct ntru_ke_t {
/**
* Implements diffie_hellman_t interface.
*/
diffie_hellman_t dh;
};
/**
* Creates a new ntru_ke_t object.
*
* @param group NTRU group number to use
* @param g not used
* @param p not used
* @return ntru_ke_t object, NULL if not supported
*/
ntru_ke_t *ntru_ke_create(diffie_hellman_group_t group, chunk_t g, chunk_t p);
#endif /** NTRU_KE_H_ @}*/

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "ntru_plugin.h"
#include "ntru_ke.h"
#include <library.h>
#include <utils/debug.h>
typedef struct private_ntru_plugin_t private_ntru_plugin_t;
rng_t *rng;
bool ntru_plugin_get_entropy(ENTROPY_CMD cmd, uint8_t *out)
{
switch (cmd)
{
case INIT:
return TRUE;
case GET_NUM_BYTES_PER_BYTE_OF_ENTROPY:
/* Here we return the number of bytes needed from the entropy
* source to obtain 8 bits of entropy. Maximum is 8.
*/
if (!out)
{
return FALSE;
}
*out = 1; /* this is a perfectly random source */
return TRUE;
case GET_BYTE_OF_ENTROPY:
if (!out)
{
return FALSE;
}
if (!rng || !rng->get_bytes(rng, 1, out))
{
return FALSE;
}
DBG2(DBG_LIB, "read one byte of entropy");
return TRUE;
default:
return FALSE;
}
}
/**
* Create/Destroy True Random Generator
*/
static bool create_random(private_ntru_plugin_t *this,
plugin_feature_t *feature, bool reg, void *data)
{
if (reg)
{
rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
if (!rng)
{
return FALSE;
}
}
else
{
rng->destroy(rng);
}
return TRUE;
}
/**
* private data of ntru_plugin
*/
struct private_ntru_plugin_t {
/**
* public functions
*/
ntru_plugin_t public;
};
METHOD(plugin_t, get_name, char*,
private_ntru_plugin_t *this)
{
return "ntru";
}
METHOD(plugin_t, get_features, int,
private_ntru_plugin_t *this, plugin_feature_t *features[])
{
int count = 0;
static plugin_feature_t f_ke[] = {
PLUGIN_REGISTER(DH, ntru_ke_create),
PLUGIN_PROVIDE(DH, NTRU_112_BIT),
PLUGIN_PROVIDE(DH, NTRU_128_BIT),
PLUGIN_PROVIDE(DH, NTRU_192_BIT),
PLUGIN_PROVIDE(DH, NTRU_256_BIT),
};
static plugin_feature_t f_rng[] = {
PLUGIN_CALLBACK((plugin_feature_callback_t)create_random, NULL),
PLUGIN_PROVIDE(CUSTOM, "ntru-rng"),
PLUGIN_DEPENDS(RNG, RNG_TRUE),
};
static plugin_feature_t f[countof(f_ke) + countof(f_rng)] = {};
plugin_features_add(f, f_ke, countof(f_ke), &count);
plugin_features_add(f, f_rng, countof(f_rng), &count);
*features = f;
return count;
}
METHOD(plugin_t, destroy, void,
private_ntru_plugin_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *ntru_plugin_create()
{
private_ntru_plugin_t *this;
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
},
);
return &this->public.plugin;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup ntru_p ntru
* @ingroup plugins
*
* @defgroup ntru_plugin ntru_plugin
* @{ @ingroup ntru_p
*/
#ifndef NTRU_PLUGIN_H_
#define NTRU_PLUGIN_H_
#include <plugins/plugin.h>
#include "ntru_crypto/ntru_crypto_drbg.h"
typedef struct ntru_plugin_t ntru_plugin_t;
/**
* Plugin implementing NTRU-base key exchange
*/
struct ntru_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Return true random bytes
*
* @param cmd command to be executed
* @param out output variable
* @result return code
*/
bool ntru_plugin_get_entropy(ENTROPY_CMD cmd, uint8_t *out);
#endif /** NTRU_PLUGIN_H_ @}*/

View File

@ -79,7 +79,8 @@ CONFIG_OPTS = \
--enable-cmd \
--enable-libipsec \
--enable-kernel-libipsec \
--enable-tkm
--enable-tkm \
--enable-ntru
export ADA_PROJECT_PATH=/usr/local/ada/lib/gnat