From: Andreas Steffen Date: Thu, 5 Dec 2013 21:55:47 +0000 (+0100) Subject: Added own MGF1 mask generating function X-Git-Tag: 5.1.2.dr2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fdc6c682b271cf24bc121e98155bc7edecb2b322;p=thirdparty%2Fstrongswan.git Added own MGF1 mask generating function --- diff --git a/src/libstrongswan/plugins/ntru/Makefile.am b/src/libstrongswan/plugins/ntru/Makefile.am index b11c081320..b1e5fe3945 100644 --- a/src/libstrongswan/plugins/ntru/Makefile.am +++ b/src/libstrongswan/plugins/ntru/Makefile.am @@ -14,7 +14,8 @@ libstrongswan_ntru_la_SOURCES = \ ntru_plugin.h ntru_plugin.c \ ntru_drbg.h ntru_drbg.c \ ntru_ke.h ntru_ke.c \ - ntru_crypto/ntru_crypto.h ntru_crypto/ntru_crypto_error.h \ + ntru_mgf1.h ntru_mgf1.c \ + ntru_crypto/ntru_crypto.h \ ntru_crypto/ntru_crypto_ntru_convert.h \ ntru_crypto/ntru_crypto_ntru_convert.c \ ntru_crypto/ntru_crypto_ntru_encrypt.c \ @@ -22,8 +23,10 @@ libstrongswan_ntru_la_SOURCES = \ ntru_crypto/ntru_crypto_ntru_encrypt_key.c \ ntru_crypto/ntru_crypto_ntru_encrypt_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_ntru_mgftp1.h \ + ntru_crypto/ntru_crypto_ntru_mgftp1.c \ + ntru_crypto/ntru_crypto_ntru_poly.h \ + ntru_crypto/ntru_crypto_ntru_poly.c libstrongswan_ntru_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h index ebd444058e..72f47035e0 100644 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h @@ -34,8 +34,6 @@ #ifndef NTRU_CRYPTO_H #define NTRU_CRYPTO_H -#include "ntru_crypto_error.h" - #include #include "ntru_drbg.h" @@ -88,10 +86,8 @@ typedef enum _NTRU_ENCRYPT_PARAM_SET_ID { #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)) - +#define NTRU_DRBG_FAIL 11 +#define NTRU_MGF1_FAIL 12 /* function declarations */ @@ -116,18 +112,14 @@ typedef enum _NTRU_ENCRYPT_PARAM_SET_ID { * 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. + * Returns NTRU_DRBG_FAIL if the DRBG handle is invalid. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL. + * Returns NTRU_BAD_LENGTH if a length argument (pubkey_blob_len or pt_len) is + * zero, or if pt_len exceeds the maximum plaintext length for the parameter set. + * Returns NTRU_BAD_PUBLIC_KEY if the public-key blob is invalid + * (unknown format, corrupt, bad length). + * Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. */ NTRUCALL @@ -159,17 +151,14 @@ ntru_crypto_ntru_encrypt( * 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. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pt) is NULL. + * Returns NTRU_BAD_LENGTH if a length argument (privkey_blob) is zero, or if + * ct_len is invalid for the parameter set. + * Returns NTRU_BAD_PRIVATE_KEY if the private-key blob is invalid + * (unknown format, corrupt, bad length). + * Returns NTRU_BUFFER_TOO_SMALL if the plaintext buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. + * Returns NTRU_FAIL if a decryption error occurs. */ NTRUCALL @@ -193,7 +182,7 @@ ntru_crypto_ntru_decrypt( * 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. + * result in this function returning NTRU_DRBG_FAIL. * * The required minimum size of the output public-key buffer (pubkey_blob) * may be queried by invoking this function with pubkey_blob = NULL. @@ -215,17 +204,15 @@ ntru_crypto_ntru_decrypt( * and *privkey_blob_len is the actual size of the private-key blob. * * 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. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pubkey_blob + * or privkey_blob) is NULL. + * Returns NTRU_INVALID_PARAMETER_SET if the parameter-set ID is invalid. + * Returns NTRU_BAD_LENGTH if a length argument is invalid. + * Returns NTRU_BUFFER_TOO_SMALL if either the pubkey_blob buffer or the + * privkey_blob buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. + * Returns 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. */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h deleted file mode 100644 index daf88e76be..0000000000 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * NTRU Cryptography Reference Source Code - * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. - * - * ntru_crypto_serror.h is a component of ntru-crypto. - * - * Copyright (C) 2009-2013 Security Innovation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - *****************************************************************************/ - - -/****************************************************************************** - * - * File: ntru_crypto_error.h - * - * Contents: Contains base values for crypto error codes. - * - *****************************************************************************/ - - -#ifndef NTRU_CRYPTO_ERROR_H -#define NTRU_CRYPTO_ERROR_H - -/* define base values for crypto error codes */ - -#define HASH_ERROR_BASE ((uint32_t)0x00000100) -#define HMAC_ERROR_BASE ((uint32_t)0x00000200) -#define SHA_ERROR_BASE ((uint32_t)0x00000400) -#define DRBG_ERROR_BASE ((uint32_t)0x00000a00) -#define NTRU_ERROR_BASE ((uint32_t)0x00003000) -#define MGF1_ERROR_BASE ((uint32_t)0x00004100) - -#endif /* NTRU_CRYPTO_ERROR_H */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c index 40d80d316a..5271d7cb37 100644 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c @@ -40,7 +40,7 @@ #include "ntru_crypto_ntru_encrypt_key.h" #include "ntru_crypto_ntru_convert.h" #include "ntru_crypto_ntru_poly.h" -#include "ntru_crypto_ntru_mgf1.h" +#include "ntru_crypto_ntru_mgftp1.h" /* ntru_crypto_ntru_encrypt * @@ -63,18 +63,14 @@ * 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. + * Returns NTRU_DRBG_FAIL if the DRBG handle is invalid. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL. + * Returns NTRU_BAD_LENGTH if a length argument (pubkey_blob_len or pt_len) is + * zero, or if pt_len exceeds the maximum plaintext length for the parameter set. + * Returns NTRU_BAD_PUBLIC_KEY if the public-key blob is invalid + * (unknown format, corrupt, bad length). + * Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. */ uint32_t @@ -107,17 +103,20 @@ ntru_crypto_ntru_encrypt( uint8_t *tmp_buf = NULL; bool msg_rep_good = FALSE; hash_algorithm_t hash_algid; - uint8_t md_len; uint16_t mprime_len = 0; uint16_t mod_q_mask; uint32_t result = NTRU_OK; /* check for bad parameters */ - if (!pubkey_blob || !pt || !ct_len) - NTRU_RET(NTRU_BAD_PARAMETER); - if ((pubkey_blob_len == 0) || (pt_len == 0)) - NTRU_RET(NTRU_BAD_LENGTH); + if (!pubkey_blob || !pt || !ct_len) + { + return NTRU_BAD_PARAMETER; + } + if ((pubkey_blob_len == 0) || (pt_len == 0)) + { + return NTRU_BAD_LENGTH; + } /* get a pointer to the parameter-set parameters, the packing type for * the public key, and a pointer to the packed public key @@ -127,37 +126,45 @@ ntru_crypto_ntru_encrypt( pubkey_blob, &pubkey_pack_type, NULL, ¶ms, &pubkey_packed, NULL)) - NTRU_RET(NTRU_BAD_PUBLIC_KEY); + { + return NTRU_BAD_PUBLIC_KEY; + } /* return the ciphertext size if requested */ packed_ct_len = (params->N * params->q_bits + 7) >> 3; - if (!ct) { + if (!ct) + { *ct_len = packed_ct_len; - NTRU_RET(NTRU_OK); + return NTRU_OK; } /* check the ciphertext buffer size */ - if (*ct_len < packed_ct_len) { - NTRU_RET(NTRU_BUFFER_TOO_SMALL); + if (*ct_len < packed_ct_len) + { + return NTRU_BUFFER_TOO_SMALL; } /* check the plaintext length */ - if (pt_len > params->m_len_max) { - NTRU_RET(NTRU_BAD_LENGTH); + if (pt_len > params->m_len_max) + { + return NTRU_BAD_LENGTH; } /* allocate memory for all operations */ - if (params->is_product_form) { + if (params->is_product_form) + { ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */ dr1 = params->dF_r & 0xff; dr2 = (params->dF_r >> 8) & 0xff; dr3 = (params->dF_r >> 16) & 0xff; dr = dr1 + dr2 + dr3; - } else { + } + else + { ring_mult_tmp_len = params->N; /* N 16-bit word buffer */ dr = params->dF_r; } @@ -170,8 +177,9 @@ ntru_crypto_ntru_encrypt( params->sec_strength_len; /* buffer for b */ scratch_buf = malloc(scratch_buf_len); - if (!scratch_buf) { - NTRU_RET(NTRU_OUT_OF_MEMORY); + if (!scratch_buf) + { + return NTRU_OUT_OF_MEMORY; } ringel_buf = scratch_buf + ring_mult_tmp_len; r_buf = ringel_buf + params->N; @@ -179,20 +187,10 @@ ntru_crypto_ntru_encrypt( tmp_buf = (uint8_t *)scratch_buf; /* set hash algorithm based on security strength */ - if (params->sec_strength_len <= 20) - { - hash_algid = HASH_SHA1; - md_len = 20; - } - else - { - hash_algid = HASH_SHA256; - md_len = 32; - } + hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256; /* set constants */ - - mod_q_mask = params->q - 1; + mod_q_mask = params->q - 1; /* loop until a message representative with proper weight is achieved */ @@ -210,10 +208,10 @@ ntru_crypto_ntru_encrypt( result = NTRU_FAIL; } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { /* form sData (OID || m || b || hTrunc) */ - memcpy(ptr, params->OID, 3); ptr += 3; memcpy(ptr, pt, pt_len); @@ -225,8 +223,7 @@ ntru_crypto_ntru_encrypt( /* generate r */ - - result = ntru_gen_poly(hash_algid, md_len, + result = ntru_gen_poly(hash_algid, params->min_IGF_hash_calls, (uint16_t)(ptr - tmp_buf), tmp_buf, tmp_buf, @@ -236,11 +233,11 @@ ntru_crypto_ntru_encrypt( params->dF_r << 1, r_buf); } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { uint16_t pubkey_packed_len; /* unpack the public key */ - assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS); pubkey_packed_len = (params->N * params->q_bits + 7) >> 3; ntru_octets_2_elements(pubkey_packed_len, pubkey_packed, @@ -259,17 +256,15 @@ ntru_crypto_ntru_encrypt( scratch_buf, ringel_buf); /* form R mod 4 */ - ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf); /* form mask */ - - result = ntru_mgftp1(hash_algid, md_len, - params->min_MGF_hash_calls, + result = ntru_mgftp1(hash_algid, params->min_MGF_hash_calls, (params->N + 3) / 4, tmp_buf, tmp_buf + params->N, params->N, tmp_buf); } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { uint8_t *Mtrin_buf = tmp_buf + params->N; uint8_t *M_buf = Mtrin_buf + params->N - (params->sec_strength_len + params->m_len_len + @@ -277,7 +272,6 @@ ntru_crypto_ntru_encrypt( uint16_t i; /* form the padded message M */ - ptr = M_buf; memcpy(ptr, b_buf, params->sec_strength_len); ptr += params->sec_strength_len; @@ -295,10 +289,11 @@ ntru_crypto_ntru_encrypt( memset(ptr, 0, params->m_len_max - pt_len + 2); /* convert M to trits (Mbin to Mtrin) */ - mprime_len = params->N; - if (params->is_product_form) + if (params->is_product_form) + { --mprime_len; + } ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf); @@ -336,7 +331,8 @@ ntru_crypto_ntru_encrypt( } } while ((result == NTRU_OK) && !msg_rep_good); - if (result == NTRU_OK) { + if (result == NTRU_OK) + { uint16_t i; /* form ciphertext e by adding m' to R mod q */ @@ -351,17 +347,15 @@ ntru_crypto_ntru_encrypt( ringel_buf[i] = (ringel_buf[i] - m1) & mod_q_mask; /* pack ciphertext */ - ntru_elements_2_octets(params->N, ringel_buf, params->q_bits, ct); *ct_len = packed_ct_len; } /* cleanup */ - memset(scratch_buf, 0, scratch_buf_len); free(scratch_buf); - return result; + return result; } @@ -381,17 +375,14 @@ ntru_crypto_ntru_encrypt( * 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. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pt) is NULL. + * Returns NTRU_BAD_LENGTH if a length argument (privkey_blob) is zero, or if + * ct_len is invalid for the parameter set. + * Returns NTRU_BAD_PRIVATE_KEY if the private-key blob is invalid + * (unknown format, corrupt, bad length). + * Returns NTRU_BUFFER_TOO_SMALL if the plaintext buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. + * Returns NTRU_FAIL if a decryption error occurs. */ uint32_t @@ -427,7 +418,6 @@ ntru_crypto_ntru_decrypt( uint8_t *M_buf = NULL; uint8_t *ptr = NULL; hash_algorithm_t hash_algid; - uint8_t md_len; uint16_t cmprime_len; uint16_t mod_q_mask; uint16_t q_mod_p; @@ -439,28 +429,35 @@ ntru_crypto_ntru_decrypt( /* check for bad parameters */ - if (!privkey_blob || !ct || !pt_len) - NTRU_RET(NTRU_BAD_PARAMETER); - if ((privkey_blob_len == 0) || (ct_len == 0)) - NTRU_RET(NTRU_BAD_LENGTH); + if (!privkey_blob || !ct || !pt_len) + { + return NTRU_BAD_PARAMETER; + } + if ((privkey_blob_len == 0) || (ct_len == 0)) + { + return NTRU_BAD_LENGTH; + } /* get a pointer to the parameter-set parameters, the packing types for * the public and private keys, and pointers to the packed public and * private keys */ - if (!ntru_crypto_ntru_encrypt_key_parse(FALSE /* privkey */, + if (!ntru_crypto_ntru_encrypt_key_parse(FALSE /* privkey */, privkey_blob_len, privkey_blob, &pubkey_pack_type, &privkey_pack_type, ¶ms, &pubkey_packed, &privkey_packed)) - NTRU_RET(NTRU_BAD_PRIVATE_KEY); + { + return NTRU_BAD_PRIVATE_KEY; + } /* return the max plaintext size if requested */ - if (!pt) { + if (!pt) + { *pt_len = params->m_len_max; - NTRU_RET(NTRU_OK); + return NTRU_OK; } /* cannot check the plaintext buffer size until after the plaintext @@ -470,12 +467,15 @@ ntru_crypto_ntru_decrypt( /* check the ciphertext length */ - if (ct_len != (params->N * params->q_bits + 7) >> 3) - NTRU_RET(NTRU_BAD_LENGTH); + if (ct_len != (params->N * params->q_bits + 7) >> 3) + { + return NTRU_BAD_LENGTH; + } /* allocate memory for all operations */ - if (params->is_product_form) { + if (params->is_product_form) + { ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */ dF_r1 = params->dF_r & 0xff; dF_r2 = (params->dF_r >> 8) & 0xff; @@ -493,8 +493,9 @@ ntru_crypto_ntru_decrypt( (dF_r << 2) + /* buffer for F, r indices */ params->m_len_max; /* buffer for plaintext */ scratch_buf = malloc(scratch_buf_len); - if (!scratch_buf) { - NTRU_RET(NTRU_OUT_OF_MEMORY); + if (!scratch_buf) + { + return NTRU_OUT_OF_MEMORY; } ringel_buf1 = scratch_buf + ring_mult_tmp_len; ringel_buf2 = ringel_buf1 + params->N; @@ -505,38 +506,31 @@ ntru_crypto_ntru_decrypt( M_buf = Mtrin_buf + params->N; /* set hash algorithm based on security strength */ - if (params->sec_strength_len <= 20) - { - hash_algid = HASH_SHA1; - md_len = 20; - } - else - { - hash_algid = HASH_SHA256; - md_len = 32; - } + hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256; /* set constants */ - mod_q_mask = params->q - 1; q_mod_p = params->q % 3; /* unpack the ciphertext */ - ntru_octets_2_elements(ct_len, ct, params->q_bits, ringel_buf2); /* unpack the private key */ - - if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) { + if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) + { ntru_packed_trits_2_indices(privkey_packed, params->N, i_buf, i_buf + dF_r); - } else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES) { + } + else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES) + { ntru_octets_2_elements( (((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3, privkey_packed, params->N_bits, i_buf); - } else { + } + else + { assert(FALSE); } @@ -548,7 +542,8 @@ ntru_crypto_ntru_decrypt( */ cmprime_len = params->N; - if (params->is_product_form) { + if (params->is_product_form) + { --cmprime_len; ntru_ring_mult_product_indices(ringel_buf2, (uint16_t)dF_r1, (uint16_t)dF_r2, (uint16_t)dF_r3, @@ -564,7 +559,9 @@ ntru_crypto_ntru_decrypt( else if (Mtrin_buf[i] == 2) --m1; } - } else { + } + else + { ntru_ring_mult_indices(ringel_buf2, (uint16_t)dF_r, (uint16_t)dF_r, i_buf, params->N, params->q, scratch_buf, ringel_buf1); @@ -581,11 +578,15 @@ ntru_crypto_ntru_decrypt( */ if (params->is_product_form) - decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) : - (bool)( m1 <= params->min_msg_rep_wt); - else + { + decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) : + (bool)( m1 <= params->min_msg_rep_wt); + } + else + { decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf, - params->min_msg_rep_wt); + params->min_msg_rep_wt); + } /* form cR = e - cm' mod q */ @@ -605,12 +606,12 @@ ntru_crypto_ntru_decrypt( /* form mask */ - result = ntru_mgftp1(hash_algid, md_len, - params->min_MGF_hash_calls, + result = ntru_mgftp1(hash_algid, params->min_MGF_hash_calls, (params->N + 3) / 4, tmp_buf, tmp_buf + params->N, params->N, tmp_buf); - if (result == NTRU_OK) { + if (result == NTRU_OK) + { /* form cMtrin by subtracting mask from cm', mod p */ @@ -665,7 +666,7 @@ ntru_crypto_ntru_decrypt( /* generate cr */ - result = ntru_gen_poly(hash_algid, md_len, + result = ntru_gen_poly(hash_algid, params->min_IGF_hash_calls, (uint16_t)(ptr - tmp_buf), tmp_buf, tmp_buf, @@ -675,7 +676,8 @@ ntru_crypto_ntru_decrypt( params->dF_r << 1, i_buf); } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { /* unpack the public key */ @@ -709,9 +711,12 @@ ntru_crypto_ntru_decrypt( /* output plaintext and plaintext length */ - if (decryption_ok) { + if (decryption_ok) + { if (*pt_len < cm_len) - NTRU_RET(NTRU_BUFFER_TOO_SMALL); + { + return NTRU_BUFFER_TOO_SMALL; + } memcpy(pt, m_buf, cm_len); *pt_len = cm_len; } @@ -723,8 +728,11 @@ ntru_crypto_ntru_decrypt( free(scratch_buf); if (!decryption_ok) - NTRU_RET(NTRU_FAIL); - return result; + { + return NTRU_FAIL; + } + + return result; } @@ -732,13 +740,6 @@ ntru_crypto_ntru_decrypt( * * Implements key generation for NTRUEncrypt for the parameter set specified. * - * 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 @@ -759,17 +760,15 @@ ntru_crypto_ntru_decrypt( * 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. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pubkey_blob or + * privkey_blob) is NULL. + * Returns NTRU_INVALID_PARAMETER_SET if the parameter-set ID is invalid. + * Returns NTRU_BAD_LENGTH if a length argument is invalid. + * Returns NTRU_BUFFER_TOO_SMALL if either the pubkey_blob buffer or the + * privkey_blob buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. + * Returns 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. */ @@ -814,12 +813,16 @@ ntru_crypto_ntru_encrypt_keygen( /* get a pointer to the parameter-set parameters */ if ((params = ntru_encrypt_get_params_with_id(param_set_id)) == NULL) - NTRU_RET(NTRU_INVALID_PARAMETER_SET); + { + return NTRU_INVALID_PARAMETER_SET; + } /* check for bad parameters */ if (!pubkey_blob_len || !privkey_blob_len) - NTRU_RET(NTRU_BAD_PARAMETER); + { + return NTRU_BAD_PARAMETER; + } /* get public and private key packing types and blob lengths */ @@ -830,22 +833,24 @@ ntru_crypto_ntru_encrypt_keygen( /* return the pubkey_blob size and/or privkey_blob size if requested */ - if (!pubkey_blob || !privkey_blob) { + if (!pubkey_blob || !privkey_blob) + { if (!pubkey_blob) *pubkey_blob_len = public_key_blob_len; if (!privkey_blob) *privkey_blob_len = private_key_blob_len; - NTRU_RET(NTRU_OK); + return NTRU_OK; } /* check size of output buffers */ if ((*pubkey_blob_len < public_key_blob_len) || (*privkey_blob_len < private_key_blob_len)) - NTRU_RET(NTRU_BUFFER_TOO_SMALL); + { + return NTRU_BUFFER_TOO_SMALL; + } /* allocate memory for all operations */ - if (params->is_product_form) { dF1 = params->dF_r & 0xff; dF2 = (params->dF_r >> 8) & 0xff; @@ -862,8 +867,9 @@ ntru_crypto_ntru_encrypt_keygen( 2N-byte buffer for f^-1 */ (dF << 2); /* buffer for F indices */ scratch_buf = malloc(scratch_buf_len); - if (!scratch_buf) { - NTRU_RET(NTRU_OUT_OF_MEMORY); + if (!scratch_buf) + { + return NTRU_OUT_OF_MEMORY; } ringel_buf1 = scratch_buf + (params->N << 1); ringel_buf2 = ringel_buf1 + params->N; @@ -897,14 +903,14 @@ ntru_crypto_ntru_encrypt_keygen( } else { - result = NTRU_FAIL; + result = NTRU_DRBG_FAIL; } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { /* generate F */ - - result = ntru_gen_poly(hash_algid, md_len, + result = ntru_gen_poly(hash_algid, params->min_IGF_hash_calls, seed_len, tmp_buf, tmp_buf, params->N, params->c_bits, @@ -913,7 +919,8 @@ ntru_crypto_ntru_encrypt_keygen( params->dF_r << 1, F_buf); } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { uint32_t i; memset(ringel_buf1, 0, params->N * sizeof(uint16_t)); @@ -967,10 +974,13 @@ ntru_crypto_ntru_encrypt_keygen( if (!ntru_ring_inv(ringel_buf1, params->N, params->q, scratch_buf, ringel_buf2)) - result = NTRU_ERROR_BASE + NTRU_FAIL; + { + result = NTRU_FAIL; + } } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { /* get random bytes for seed for generating trinary g * as a list of indices @@ -978,18 +988,19 @@ ntru_crypto_ntru_encrypt_keygen( if (!drbg->generate(drbg, params->sec_strength_len << 3, seed_len, tmp_buf)) { - result = NTRU_FAIL; + result = NTRU_DRBG_FAIL; } } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { uint16_t min_IGF_hash_calls = ((((params->dg << 2) + 2) * params->N_bits) + (md_len << 3) - 1) / (md_len << 3); /* generate g */ - result = ntru_gen_poly(hash_algid, md_len, + result = ntru_gen_poly(hash_algid, (uint8_t)min_IGF_hash_calls, seed_len, tmp_buf, tmp_buf, params->N, params->c_bits, @@ -997,7 +1008,8 @@ ntru_crypto_ntru_encrypt_keygen( (params->dg << 1) + 1, ringel_buf1); } - if (result == NTRU_OK) { + if (result == NTRU_OK) + { uint16_t i; /* compute h = p * (f^-1 * g) mod q */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.c similarity index 55% rename from src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c rename to src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.c index fbbd6b63ed..d0427982bc 100644 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.c @@ -2,7 +2,7 @@ * 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. + * ntru_crypto_ntru_mgftp1.c is a component of ntru-crypto. * * Copyright (C) 2009-2013 Security Innovation * @@ -24,93 +24,19 @@ /****************************************************************************** * - * File: ntru_crypto_ntru_mgf1.c + * File: ntru_crypto_ntru_mgftp1.c * - * Contents: Routines implementing MGF-TP-1 and MGF-1. + * Contents: Routines implementing MGF-TP-1. * *****************************************************************************/ #include #include -#include -#include "ntru_crypto_ntru_mgf1.h" +#include "ntru_crypto_ntru_mgftp1.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 */ - hash_algorithm_t hash_algid, /* in - hash algorithm ID */ - uint8_t md_len, /* in - no. of octets in digest */ - uint8_t num_calls, /* in - no. of hash calls */ - uint16_t seed_len, /* in - no. of octets in seed */ - uint8_t *seed, /* in - pointer to seed */ - uint8_t *out) /* out - address for output */ -{ - uint8_t *ctr = state + md_len; - hasher_t *hasher; - - assert(state); - assert(out); - - hasher = lib->crypto->create_hasher(lib->crypto, hash_algid); - if (!hasher) - { - NTRU_RET(NTRU_FAIL); - } - - /* if seed present, init state */ - if (seed) - { - if (!hasher->get_hash(hasher, chunk_create(seed, seed_len), state)) - { - hasher->destroy(hasher); - NTRU_RET(NTRU_FAIL); - } - memset(ctr, 0, 4); - } - - /* generate output */ - while (num_calls-- > 0) - { - if (!hasher->get_hash(hasher, chunk_create(state, md_len + 4), out)) - { - hasher->destroy(hasher); - NTRU_RET(NTRU_FAIL); - } - out += md_len; - - /* increment counter */ - if (++ctr[3] == 0) - { - if (++ctr[2] == 0) - { - if (++ctr[1] == 0) - { - ++ctr[0]; - } - } - } - } - hasher->destroy(hasher); - - NTRU_RET(NTRU_OK); -} - +#include "ntru_mgf1.h" /* ntru_mgftp1 * @@ -122,7 +48,7 @@ ntru_mgf1( * 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. + * Returns NTRU_MGF1_FAIL if the MGF1 mask generator function fails * */ @@ -130,8 +56,6 @@ uint32_t ntru_mgftp1( hash_algorithm_t 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 */ @@ -141,38 +65,43 @@ ntru_mgftp1( 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 md_len; uint8_t *octets; uint16_t octets_available; - uint32_t retcode; - - assert(seed); - assert(buf); - assert(mask); + ntru_mgf1_t *mgf1; /* 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) + mgf1 = ntru_mgf1_create(hash_algid, chunk_create(seed, seed_len), TRUE); + if (!mgf1) { - return retcode; + return NTRU_MGF1_FAIL; } - octets = mgf_out; + md_len = mgf1->get_hash_size(mgf1); + octets = buf; octets_available = min_calls * md_len; + DBG2(DBG_LIB, "MGF1 generates %u octets", octets_available); + if (!mgf1->get_mask(mgf1, octets_available, octets)) + { + mgf1->destroy(mgf1); + return NTRU_MGF1_FAIL; + } + /* get trits for mask */ 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) + octets = buf; + octets_available = md_len; + + DBG2(DBG_LIB, "MGF1 generates another %u octets", octets_available); + if (!mgf1->get_mask(mgf1, octets_available, octets)) { - return retcode; + mgf1->destroy(mgf1); + return NTRU_MGF1_FAIL; } - octets = mgf_out; - octets_available = md_len; } if (*octets < 243) @@ -193,13 +122,15 @@ ntru_mgftp1( /* 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) + octets = buf; + octets_available = md_len; + + DBG2(DBG_LIB, "MGF1 generates another %u octets", octets_available); + if (!mgf1->get_mask(mgf1, octets_available, octets)) { - return retcode; + mgf1->destroy(mgf1); + return NTRU_MGF1_FAIL; } - octets = mgf_out; - octets_available = md_len; } if (*octets < 243) { @@ -213,8 +144,9 @@ ntru_mgftp1( --octets_available; } } + mgf1->destroy(mgf1); - NTRU_RET(NTRU_OK); + return NTRU_OK; } diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.h similarity index 67% rename from src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h rename to src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.h index 43d710217c..6f85efc898 100644 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.h @@ -2,7 +2,7 @@ * 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. + * ntru_crypto_ntru_mgftp1.h is a component of ntru-crypto. * * Copyright (C) 2009-2013 Security Innovation * @@ -24,9 +24,9 @@ /****************************************************************************** * - * File: ntru_crypto_ntru_mgf1.h + * File: ntru_crypto_ntru_mgftp1.h * - * Contents: Public header file for MGF-1 in the NTRU algorithm. + * Contents: Public header file for MGF-TP-1 in the NTRU algorithm. * *****************************************************************************/ @@ -39,32 +39,6 @@ #include -/* function declarations */ - -/* ntru_mgf1 - * - * Implements a basic mask-generation function, generating an arbitrary - * number of octets based on hashing a digest-length string concatenated - * with a 4-octet counter. - * - * The state (string and counter) is initialized when a seed is present. - * - * Returns NTRU_OK if successful. - * Returns NTRU_CRYPTO_HASH_ errors if they occur. - * - */ - -extern uint32_t -ntru_mgf1( - uint8_t *state, /* in/out - pointer to the state */ - hash_algorithm_t hash_algid, /* in - hash algorithm ID */ - uint8_t md_len, /* in - no. of octets in digest */ - uint8_t num_calls, /* in - no. of hash calls */ - uint16_t seed_len, /* in - no. of octets in seed */ - uint8_t *seed, /* in - pointer to seed */ - uint8_t *out); /* out - address for output */ - - /* ntru_mgftp1 * * Implements a mask-generation function for trinary polynomials, @@ -83,8 +57,6 @@ extern uint32_t ntru_mgftp1( hash_algorithm_t 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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c index be45954373..955544f2f8 100644 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c @@ -34,10 +34,12 @@ #include #include -#include #include "ntru_crypto_ntru_poly.h" -#include "ntru_crypto_ntru_mgf1.h" +#include "ntru_crypto_ntru_mgftp1.h" +#include "ntru_mgf1.h" + +#include /* ntru_gen_poly * @@ -64,7 +66,6 @@ uint32_t ntru_gen_poly( hash_algorithm_t 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 */ @@ -80,7 +81,7 @@ ntru_gen_poly( uint32_t indices_counts, /* in - nos. of indices needed */ uint16_t *indices) /* out - address for indices */ { - uint8_t *mgf_out; + uint8_t md_len; uint8_t *octets; uint8_t *used; uint8_t num_polys; @@ -89,23 +90,26 @@ ntru_gen_poly( uint16_t index_cnt = 0; uint8_t left = 0; uint8_t num_left = 0; - uint32_t retcode; - - assert(seed); - assert(buf); - assert(indices); + ntru_mgf1_t *mgf1; /* 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; + mgf1 = ntru_mgf1_create(hash_algid, chunk_create(seed, seed_len), TRUE); + if (!mgf1) + { + return NTRU_MGF1_FAIL; + } + md_len = mgf1->get_hash_size(mgf1); + octets = buf; octets_available = min_calls * md_len; - /* init indices counts for number of polynomials being generated */ + DBG2(DBG_LIB, "MGF1 generates %u octets", octets_available); + if (!mgf1->get_mask(mgf1, octets_available, octets)) + { + mgf1->destroy(mgf1); + return NTRU_MGF1_FAIL; + } + /* init indices counts for number of polynomials being generated */ if (is_product_form) { /* number of indices for poly1 is in low byte of indices_counts, @@ -126,7 +130,7 @@ ntru_gen_poly( /* init used-index array */ - used = mgf_out + octets_available; + used = buf + octets_available; memset(used, 0, N); /* generate indices (IGF-2) for all polynomials */ @@ -153,21 +157,28 @@ ntru_gen_poly( /* get the rest of the bits needed from new octets */ num_needed = c_bits - num_left; - while (num_needed != 0) { + 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; + if (octets_available == 0) + { + octets = buf; octets_available = md_len; + + DBG2(DBG_LIB, "MGF1 generates another %u octets", + octets_available); + if (!mgf1->get_mask(mgf1, octets_available, octets)) + { + mgf1->destroy(mgf1); + return NTRU_MGF1_FAIL; + } } left = *octets++; --octets_available; - if (num_needed <= 8) { + if (num_needed <= 8) + { /* all bits needed to fill the index are in this octet */ @@ -191,7 +202,8 @@ ntru_gen_poly( /* form index and check if unique */ index %= N; - if (!used[index]) { + if (!used[index]) + { used[index] = 1; indices[index_cnt] = index; ++index_cnt; @@ -201,15 +213,17 @@ ntru_gen_poly( /* init for next polynomial if another polynomial to be generated */ - if (num_polys > 0) { + if (num_polys > 0) + { memset(used, 0, N); num_indices = num_indices + (uint16_t)(indices_counts & 0xff); indices_counts >>= 8; } } + mgf1->destroy(mgf1); - NTRU_RET(NTRU_OK); + return NTRU_OK; } @@ -276,11 +290,6 @@ ntru_ring_mult_indices( uint16_t mod_q_mask = q - 1; uint16_t 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++) @@ -356,27 +365,19 @@ ntru_ring_mult_product_indices( 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; } @@ -406,12 +407,7 @@ ntru_ring_mult_coefficients( 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; @@ -457,31 +453,22 @@ ntru_ring_inv( 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 */ + 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; @@ -489,7 +476,8 @@ ntru_ring_inv( /* until f(X) = 1 */ - while (!done) { + while (!done) + { /* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h index 33939fe058..9d0406b0d0 100644 --- a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h @@ -68,7 +68,6 @@ extern uint32_t ntru_gen_poly( hash_algorithm_t 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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_mgf1.c b/src/libstrongswan/plugins/ntru/ntru_mgf1.c new file mode 100644 index 0000000000..5a1770363d --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_mgf1.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ntru_mgf1.h" + +#include +#include +#include + +typedef struct private_ntru_mgf1_t private_ntru_mgf1_t; + +/** + * Private data of an ntru_mgf1_t object. + */ +struct private_ntru_mgf1_t { + + /** + * Public ntru_mgf1_t interface. + */ + ntru_mgf1_t public; + + /** + * Hasher the MGF1 Mask Generation Function is based on + */ + hasher_t *hasher; + + /** + * Counter + */ + u_int32_t counter; + + /** + * Set if counter has reached 2^32 + */ + bool overflow; + + /** + * Current state to be hashed + */ + chunk_t state; + + /** + * Position of the 4 octet counter string + */ + u_char *ctr_str; + +}; + +METHOD(ntru_mgf1_t, get_hash_size, size_t, + private_ntru_mgf1_t *this) +{ + return this->hasher->get_hash_size(this->hasher); +} + +METHOD(ntru_mgf1_t, get_mask, bool, + private_ntru_mgf1_t *this, size_t mask_len, u_char *mask) +{ + u_char buf[HASH_SIZE_SHA512]; + size_t len; + + while (mask_len > 0) + { + /* detect overflow, set counter string and increment counter */ + if (this->overflow) + { + return FALSE; + } + htoun32(this->ctr_str, this->counter++); + if (this->counter == 0) + { + this->overflow = TRUE; + } + + if (!this->hasher->get_hash(this->hasher, this->state, buf)) + { + return FALSE; + } + + len = min(mask_len, this->hasher->get_hash_size(this->hasher)); + memcpy(mask, buf, len); + mask_len -= len; + mask += len; + } + + return TRUE; +} + +METHOD(ntru_mgf1_t, allocate_mask, bool, + private_ntru_mgf1_t *this, size_t mask_len, chunk_t *mask) +{ + if (mask_len == 0) + { + *mask = chunk_empty; + return TRUE; + } + *mask = chunk_alloc(mask_len); + + return get_mask(this, mask_len, mask->ptr); +} + +METHOD(ntru_mgf1_t, destroy, void, + private_ntru_mgf1_t *this) +{ + this->hasher->destroy(this->hasher); + chunk_clear(&this->state); + free(this); +} + +/* + * Described in header. + */ +ntru_mgf1_t *ntru_mgf1_create(hash_algorithm_t alg, chunk_t seed, + bool hash_seed) +{ + private_ntru_mgf1_t *this; + hasher_t *hasher; + size_t state_len; + + if (seed.len == 0) + { + DBG1(DBG_LIB, "empty seed for MGF1"); + return NULL; + } + + hasher = lib->crypto->create_hasher(lib->crypto, alg); + if (!hasher) + { + DBG1(DBG_LIB, "failed to create %N hasher for MGF1", + hash_algorithm_names, alg); + return NULL; + } + state_len = (hash_seed ? hasher->get_hash_size(hasher) : seed.len) + 4; + + INIT(this, + .public = { + .get_hash_size = _get_hash_size, + .allocate_mask = _allocate_mask, + .get_mask = _get_mask, + .destroy = _destroy, + }, + .hasher = hasher, + .state = chunk_alloc(state_len), + ); + + /* determine position of the 4 octet counter string */ + this->ctr_str = this->state.ptr + state_len - 4; + + if (hash_seed) + { + if (!hasher->get_hash(hasher, seed, this->state.ptr)) + { + DBG1(DBG_LIB, "failed to hash seed for MGF1"); + destroy(this); + return NULL; + } + } + else + { + memcpy(this->state.ptr, seed.ptr, seed.len); + } + + return &this->public; +} + +EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_mgf1_create); diff --git a/src/libstrongswan/plugins/ntru/ntru_mgf1.h b/src/libstrongswan/plugins/ntru/ntru_mgf1.h new file mode 100644 index 0000000000..53e90412a5 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_mgf1.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup ntru_mgf1 ntru_mgf1 + * @{ @ingroup ntru_p + */ + +#ifndef NTRU_MGF1_H_ +#define NTRU_MGF1_H_ + +typedef struct ntru_mgf1_t ntru_mgf1_t; + +#include + +/** + * Implements the PKCS#1 MGF1 Mask Generation Function based on a hash function + * defined in section 10.2.1 of RFC 2437 + */ +struct ntru_mgf1_t { + + /** + * Get the hash size of the underlying hash function + * + * @return hash size in bytes + */ + size_t (*get_hash_size)(ntru_mgf1_t *this); + + /** + * Generate a mask pattern and copy it to an output buffer + * If the maximum number of requests has been reached, reseeding occurs + * + * @param mask_len number of mask bytes to generate + * @param mask output buffer of minimum size mask_len + * @return TRUE if successful + */ + bool (*get_mask)(ntru_mgf1_t *this, size_t mask_len, u_char *mask); + + /** + * Generate a mask pattern and return it in an allocated chunk + * + * @param mask_len number of mask bytes to generate + * @param mask chunk containing generated mask + * @return TRUE if successful + */ + bool (*allocate_mask)(ntru_mgf1_t *this, size_t mask_len, chunk_t *mask); + + /** + * Destroy the MGF1 object + */ + void (*destroy)(ntru_mgf1_t *this); +}; + +/** + * Create an MGF1 object + * + * @param alg hash algorithm to be used by MGF1 + * @param seed seed used by MGF1 to generate mask from + * @param hash_seed hash seed before using it as a seed from MGF1 + */ +ntru_mgf1_t *ntru_mgf1_create(hash_algorithm_t alg, chunk_t seed, + bool hash_seed); + +#endif /** NTRU_MGF1_H_ @}*/ + diff --git a/src/libstrongswan/tests/suites/test_ntru.c b/src/libstrongswan/tests/suites/test_ntru.c index 73156208f6..2548d3134d 100644 --- a/src/libstrongswan/tests/suites/test_ntru.c +++ b/src/libstrongswan/tests/suites/test_ntru.c @@ -17,11 +17,15 @@ #include #include +#include #include IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create, ntru_drbg_t*, u_int32_t strength, chunk_t pers_str, rng_t *entropy) +IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_mgf1_create, ntru_mgf1_t*, + hash_algorithm_t alg, chunk_t seed, bool hash_seed) + /** * NTRU parameter sets to test */ @@ -286,6 +290,169 @@ START_TEST(test_ntru_drbg_reseed) } END_TEST +typedef struct { + hash_algorithm_t alg; + size_t hash_size; + size_t ml1, ml2, ml3; + chunk_t seed; + chunk_t hashed_seed; + chunk_t mask; +} mgf1_test_t; + +/** + * MGF1 Mask Generation Function Test Vectors + */ +mgf1_test_t mgf1_tests[] = { + { HASH_SHA1, 20, 60, 20, 15, + chunk_from_chars( + 0xED, 0xA5, 0xC3, 0xBC, 0xAF, 0xB3, 0x20, 0x7D, + 0x14, 0xA1, 0x54, 0xF7, 0x8B, 0x37, 0xF2, 0x8D, + 0x8C, 0x9B, 0xD5, 0x63, 0x57, 0x38, 0x11, 0xC2, + 0xB5, 0xCA, 0xBF, 0x06, 0x43, 0x45, 0x19, 0xD5, + 0xE7, 0x36, 0xD0, 0x29, 0x21, 0xDA, 0x02, 0x20, + 0x45, 0xF6, 0x5F, 0x0F, 0x10, 0x04, 0x2A, 0xE3, + 0x6A, 0x1D, 0xD5, 0x9F, 0x1D, 0x66, 0x44, 0x8F, + 0xFA, 0xC6, 0xCA, 0xA4, 0x6E, 0x3B, 0x00, 0x66, + 0xA6, 0xC9, 0x80, 0x5C, 0xF5, 0x2D, 0xD7, 0x72, + 0xC6, 0xD4, 0x4F, 0x30, 0x72, 0xA2, 0xAD, 0xE0, + 0x33, 0xE8, 0x55, 0xD5, 0xE6, 0xD6, 0x00, 0x1D, + 0xA8, 0x68, 0xFF, 0x97, 0x36, 0x8A, 0xF4, 0xD6, + 0xF1, 0xB6, 0x7E, 0x1F, 0x06, 0xCB, 0x57, 0xCB, + 0x35, 0x38, 0xF2, 0x2D, 0xF6, 0x20), + chunk_from_chars( + 0xF3, 0x9B, 0x0B, 0xB4, 0x97, 0x50, 0xB5, 0xA7, + 0xE6, 0xBD, 0xDA, 0xD0, 0x9A, 0x52, 0xBE, 0xA0, + 0x21, 0xC4, 0x90, 0xB6), + chunk_from_chars( + 0x10, 0x43, 0x76, 0x72, 0x6C, 0xDE, 0xA0, 0x0E, + 0x77, 0x51, 0xFB, 0x58, 0x39, 0x8A, 0x36, 0xE1, + 0x63, 0x2B, 0xC9, 0x17, 0x56, 0x0C, 0x4B, 0x46, + 0xA4, 0x07, 0xA4, 0x3B, 0x8E, 0x33, 0x4D, 0xD1, + 0x65, 0xF1, 0xAC, 0xC8, 0x59, 0x21, 0x32, 0x16, + 0x44, 0x2B, 0x7F, 0xB2, 0xA8, 0xA7, 0x26, 0x5D, + 0xE8, 0x02, 0xBE, 0x8E, 0xDC, 0x34, 0xEB, 0x10, + 0x76, 0x16, 0x8C, 0xDD, 0x90, 0x92, 0x3D, 0x29, + 0x90, 0x98, 0x46, 0x11, 0x73, 0x53, 0x47, 0xB1, + 0x2C, 0xD4, 0x83, 0x78, 0x9B, 0x93, 0x2F, 0x5B, + 0xFC, 0x26, 0xFF, 0x42, 0x08, 0x1F, 0x70, 0x66, + 0x40, 0x4B, 0xE7, 0x22, 0x3A, 0x56, 0x10, 0x6D, + 0x4D, 0x29, 0x0B, 0xCE, 0xA6, 0x21, 0xB5, 0x5C, + 0x71, 0x66, 0x2F, 0x70, 0x35, 0xD8, 0x8A, 0x92, + 0x33, 0xF0, 0x16, 0xD4, 0x0E, 0x43, 0x8A, 0x14) }, + { HASH_SHA256, 32, 64, 32, 33, + chunk_from_chars( + 0x52, 0xC5, 0xDD, 0x1E, 0xEF, 0x76, 0x1B, 0x53, + 0x08, 0xE4, 0x86, 0x3F, 0x91, 0x12, 0x98, 0x69, + 0xC5, 0x9D, 0xDE, 0xF6, 0xFC, 0xFA, 0x93, 0xCE, + 0x32, 0x52, 0x66, 0xF9, 0xC9, 0x97, 0xF6, 0x42, + 0x00, 0x2C, 0x64, 0xED, 0x1A, 0x6B, 0x14, 0x0A, + 0x4B, 0x04, 0xCF, 0x6D, 0x2D, 0x82, 0x0A, 0x07, + 0xA2, 0x3B, 0xDE, 0xCE, 0x19, 0x8A, 0x39, 0x43, + 0x16, 0x61, 0x29, 0x98, 0x68, 0xEA, 0xE5, 0xCC, + 0x0A, 0xF8, 0xE9, 0x71, 0x26, 0xF1, 0x07, 0x36, + 0x2C, 0x07, 0x1E, 0xEB, 0xE4, 0x28, 0xA2, 0xF4, + 0xA8, 0x12, 0xC0, 0xC8, 0x20, 0x37, 0xF8, 0xF2, + 0x6C, 0xAF, 0xDC, 0x6F, 0x2E, 0xD0, 0x62, 0x58, + 0xD2, 0x37, 0x03, 0x6D, 0xFA, 0x6E, 0x1A, 0xAC, + 0x9F, 0xCA, 0x56, 0xC6, 0xA4, 0x52, 0x41, 0xE8, + 0x0F, 0x1B, 0x0C, 0xB9, 0xE6, 0xBA, 0xDE, 0xE1, + 0x03, 0x5E, 0xC2, 0xE5, 0xF8, 0xF4, 0xF3, 0x46, + 0x3A, 0x12, 0xC0, 0x1F, 0x3A, 0x00, 0xD0, 0x91, + 0x18, 0xDD, 0x53, 0xE4, 0x22, 0xF5, 0x26, 0xA4, + 0x54, 0xEE, 0x20, 0xF0, 0x80), + chunk_from_chars( + 0x76, 0x89, 0x8B, 0x1B, 0x60, 0xEC, 0x10, 0x9D, + 0x8F, 0x13, 0xF2, 0xFE, 0xD9, 0x85, 0xC1, 0xAB, + 0x7E, 0xEE, 0xB1, 0x31, 0xDD, 0xF7, 0x7F, 0x0C, + 0x7D, 0xF9, 0x6B, 0x7B, 0x19, 0x80, 0xBD, 0x28), + chunk_from_chars( + 0xF1, 0x19, 0x02, 0x4F, 0xDA, 0x58, 0x05, 0x9A, + 0x07, 0xDF, 0x61, 0x81, 0x22, 0x0E, 0x15, 0x46, + 0xCB, 0x35, 0x3C, 0xDC, 0xAD, 0x20, 0xD9, 0x3F, + 0x0D, 0xD1, 0xAA, 0x64, 0x66, 0x5C, 0xFA, 0x4A, + 0xFE, 0xD6, 0x8F, 0x55, 0x57, 0x15, 0xB2, 0xA6, + 0xA0, 0xE6, 0xA8, 0xC6, 0xBD, 0x28, 0xB4, 0xD5, + 0x6E, 0x5B, 0x4B, 0xB0, 0x97, 0x09, 0xF5, 0xAC, + 0x57, 0x65, 0x13, 0x97, 0x71, 0x2C, 0x45, 0x13, + 0x3D, 0xEE, 0xFB, 0xBF, 0xFE, 0xAF, 0xBB, 0x4B, + 0x0D, 0x5C, 0x45, 0xD4, 0x2F, 0x17, 0x92, 0x07, + 0x66, 0x11, 0xF5, 0x46, 0xF8, 0x0C, 0x03, 0x92, + 0xF5, 0xF5, 0xFF, 0xA4, 0xF3, 0x52, 0xF4, 0x08, + 0x2C, 0x49, 0x32, 0x1A, 0x93, 0x51, 0x98, 0xB6, + 0x94, 0x83, 0x39, 0xCF, 0x6B, 0x1F, 0x2F, 0xFC, + 0x2B, 0xFF, 0x10, 0x71, 0x7D, 0x35, 0x6C, 0xEA, + 0xC5, 0x66, 0xC7, 0x26, 0x7D, 0x9E, 0xAC, 0xDD, + 0x35, 0xD7, 0x06, 0x3F, 0x40, 0x82, 0xDA, 0xC3, + 0x2B, 0x3C, 0x91, 0x3A, 0x32, 0xF8, 0xB2, 0xC6, + 0x44, 0x4D, 0xCD, 0xB6, 0x54, 0x5F, 0x81, 0x95, + 0x59, 0xA1, 0xE5, 0x4E, 0xA5, 0x0A, 0x4A, 0x42) } +}; + +START_TEST(test_ntru_mgf1) +{ + ntru_mgf1_t *mgf1; + chunk_t mask, mask1, mask2, mask3; + + mask1 = mgf1_tests[_i].mask; + mask2 = chunk_skip(mask1, mgf1_tests[_i].ml1); + mask3 = chunk_skip(mask2, mgf1_tests[_i].ml2); + mask1.len = mgf1_tests[_i].ml1; + mask2.len = mgf1_tests[_i].ml2; + mask3.len = mgf1_tests[_i].ml3; + + mgf1 = ntru_mgf1_create(HASH_UNKNOWN, mgf1_tests[_i].seed, TRUE); + ck_assert(mgf1 == NULL); + + mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, chunk_empty, TRUE); + ck_assert(mgf1 == NULL); + + /* return mask in allocated chunk */ + mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE); + ck_assert(mgf1); + + /* check hash size */ + ck_assert(mgf1->get_hash_size(mgf1) == mgf1_tests[_i].hash_size); + + /* get zero number of octets */ + ck_assert(mgf1->allocate_mask(mgf1, 0, &mask)); + ck_assert(mask.len == 0 && mask.ptr == NULL); + + /* get non-zero number of octets */ + ck_assert(mgf1->allocate_mask(mgf1, mgf1_tests[_i].mask.len, &mask)); + ck_assert(chunk_equals(mask, mgf1_tests[_i].mask)); + mgf1->destroy(mgf1); + + /* copy mask to pre-allocated buffer */ + mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE); + ck_assert(mgf1); + ck_assert(mgf1->get_mask(mgf1, mgf1_tests[_i].mask.len, mask.ptr)); + ck_assert(chunk_equals(mask, mgf1_tests[_i].mask)); + mgf1->destroy(mgf1); + + /* get mask in batches without hashing the seed */ + mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].hashed_seed, FALSE); + ck_assert(mgf1); + + /* first batch */ + ck_assert(mgf1->get_mask(mgf1, mask1.len, mask.ptr)); + mask.len = mask1.len; + ck_assert(chunk_equals(mask, mask1)); + + /* second batch */ + ck_assert(mgf1->get_mask(mgf1, mask2.len, mask.ptr)); + mask.len = mask2.len; + ck_assert(chunk_equals(mask, mask2)); + + /* third batch */ + ck_assert(mgf1->get_mask(mgf1, mask3.len, mask.ptr)); + mask.len = mask3.len; + ck_assert(chunk_equals(mask, mask3)); + + mgf1->destroy(mgf1); + chunk_free(&mask); +} +END_TEST + START_TEST(test_ntru_ke) { chunk_t pub_key, cipher_text, i_shared_secret, r_shared_secret; @@ -488,6 +655,10 @@ Suite *ntru_suite_create() tcase_add_test(tc, test_ntru_drbg_reseed); suite_add_tcase(s, tc); + tc = tcase_create("mgf1"); + tcase_add_loop_test(tc, test_ntru_mgf1, 0, countof(mgf1_tests)); + suite_add_tcase(s, tc); + tc = tcase_create("ke"); tcase_add_loop_test(tc, test_ntru_ke, 0, countof(params)); suite_add_tcase(s, tc);