diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2014-03-11 20:48:48 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2014-03-11 20:48:48 +0100 |
commit | 15fb7904f4431a6e7c305fd08732458f7f885e7e (patch) | |
tree | c93b60ee813af70509f00f34e29ebec311762427 /src/libstrongswan/plugins/ntru | |
parent | 5313d2d78ca150515f7f5eb39801c100690b6b29 (diff) | |
download | vyos-strongswan-15fb7904f4431a6e7c305fd08732458f7f885e7e.tar.gz vyos-strongswan-15fb7904f4431a6e7c305fd08732458f7f885e7e.zip |
Imported Upstream version 5.1.2
Diffstat (limited to 'src/libstrongswan/plugins/ntru')
24 files changed, 6123 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/ntru/Makefile.am b/src/libstrongswan/plugins/ntru/Makefile.am new file mode 100644 index 000000000..b33cbc8c9 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/Makefile.am @@ -0,0 +1,33 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = \ + -rdynamic @COVERAGE_CFLAGS@ + +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_drbg.h ntru_drbg.c \ + ntru_ke.h ntru_ke.c \ + ntru_mgf1.h ntru_mgf1.c \ + ntru_poly.h ntru_poly.c \ + ntru_trits.h ntru_trits.c \ + ntru_crypto/ntru_crypto.h \ + ntru_crypto/ntru_crypto_ntru_convert.h \ + ntru_crypto/ntru_crypto_ntru_convert.c \ + ntru_crypto/ntru_crypto_ntru_encrypt.c \ + ntru_crypto/ntru_crypto_ntru_encrypt_key.h \ + ntru_crypto/ntru_crypto_ntru_encrypt_key.c \ + ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h \ + ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.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/Makefile.in b/src/libstrongswan/plugins/ntru/Makefile.in new file mode 100644 index 000000000..af192d203 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/Makefile.in @@ -0,0 +1,812 @@ +# Makefile.in generated by automake 1.13.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libstrongswan/plugins/ntru +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_ntru_la_LIBADD = +am__dirstamp = $(am__leading_dot)dirstamp +am_libstrongswan_ntru_la_OBJECTS = ntru_plugin.lo ntru_drbg.lo \ + ntru_ke.lo ntru_mgf1.lo ntru_poly.lo ntru_trits.lo \ + ntru_crypto/ntru_crypto_ntru_convert.lo \ + ntru_crypto/ntru_crypto_ntru_encrypt.lo \ + ntru_crypto/ntru_crypto_ntru_encrypt_key.lo \ + ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.lo \ + ntru_crypto/ntru_crypto_ntru_poly.lo +libstrongswan_ntru_la_OBJECTS = $(am_libstrongswan_ntru_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_ntru_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_ntru_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_ntru_la_rpath = -rpath $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_ntru_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_ntru_la_SOURCES) +DIST_SOURCES = $(libstrongswan_ntru_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = \ + -rdynamic @COVERAGE_CFLAGS@ + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ntru.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ntru.la +libstrongswan_ntru_la_SOURCES = \ + ntru_plugin.h ntru_plugin.c \ + ntru_drbg.h ntru_drbg.c \ + ntru_ke.h ntru_ke.c \ + ntru_mgf1.h ntru_mgf1.c \ + ntru_poly.h ntru_poly.c \ + ntru_trits.h ntru_trits.c \ + ntru_crypto/ntru_crypto.h \ + ntru_crypto/ntru_crypto_ntru_convert.h \ + ntru_crypto/ntru_crypto_ntru_convert.c \ + ntru_crypto/ntru_crypto_ntru_encrypt.c \ + ntru_crypto/ntru_crypto_ntru_encrypt_key.h \ + ntru_crypto/ntru_crypto_ntru_encrypt_key.c \ + ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h \ + ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c \ + ntru_crypto/ntru_crypto_ntru_poly.h \ + ntru_crypto/ntru_crypto_ntru_poly.c + +libstrongswan_ntru_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/ntru/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libstrongswan/plugins/ntru/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +ntru_crypto/$(am__dirstamp): + @$(MKDIR_P) ntru_crypto + @: > ntru_crypto/$(am__dirstamp) +ntru_crypto/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ntru_crypto/$(DEPDIR) + @: > ntru_crypto/$(DEPDIR)/$(am__dirstamp) +ntru_crypto/ntru_crypto_ntru_convert.lo: ntru_crypto/$(am__dirstamp) \ + ntru_crypto/$(DEPDIR)/$(am__dirstamp) +ntru_crypto/ntru_crypto_ntru_encrypt.lo: ntru_crypto/$(am__dirstamp) \ + ntru_crypto/$(DEPDIR)/$(am__dirstamp) +ntru_crypto/ntru_crypto_ntru_encrypt_key.lo: \ + ntru_crypto/$(am__dirstamp) \ + ntru_crypto/$(DEPDIR)/$(am__dirstamp) +ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.lo: \ + ntru_crypto/$(am__dirstamp) \ + ntru_crypto/$(DEPDIR)/$(am__dirstamp) +ntru_crypto/ntru_crypto_ntru_poly.lo: ntru_crypto/$(am__dirstamp) \ + ntru_crypto/$(DEPDIR)/$(am__dirstamp) + +libstrongswan-ntru.la: $(libstrongswan_ntru_la_OBJECTS) $(libstrongswan_ntru_la_DEPENDENCIES) $(EXTRA_libstrongswan_ntru_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_ntru_la_LINK) $(am_libstrongswan_ntru_la_rpath) $(libstrongswan_ntru_la_OBJECTS) $(libstrongswan_ntru_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ntru_crypto/*.$(OBJEXT) + -rm -f ntru_crypto/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntru_drbg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntru_ke.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntru_mgf1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntru_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntru_poly.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntru_trits.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ntru_crypto/$(DEPDIR)/ntru_crypto_ntru_convert.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ntru_crypto/$(DEPDIR)/ntru_crypto_ntru_encrypt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ntru_crypto/$(DEPDIR)/ntru_crypto_ntru_encrypt_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ntru_crypto/$(DEPDIR)/ntru_crypto_ntru_encrypt_param_sets.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ntru_crypto/$(DEPDIR)/ntru_crypto_ntru_poly.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf ntru_crypto/.libs ntru_crypto/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ntru_crypto/$(DEPDIR)/$(am__dirstamp) + -rm -f ntru_crypto/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) ntru_crypto/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) ntru_crypto/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pluginLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h new file mode 100644 index 000000000..72f47035e --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * NTRU Cryptography Reference Source Code + * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. + * + * ntru_crypto.h is a component of ntru-crypto. + * + * Copyright (C) 2009-2013 Security Innovation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *****************************************************************************/ + + +/****************************************************************************** + * + * File: ntru_crypto.h + * + * Contents: Public header file for NTRUEncrypt. + * + *****************************************************************************/ + +#ifndef NTRU_CRYPTO_H +#define NTRU_CRYPTO_H + +#include <library.h> + +#include "ntru_drbg.h" + +#if !defined( NTRUCALL ) + #if !defined(WIN32) || defined (NTRUCRYPTO_STATIC) + // Linux, or a Win32 static library + #define NTRUCALL extern uint32_t + #elif defined (NTRUCRYPTO_EXPORTS) + // Win32 DLL build + #define NTRUCALL extern __declspec(dllexport) uint32_t + #else + // Win32 DLL import + #define NTRUCALL extern __declspec(dllimport) uint32_t + #endif +#endif /* NTRUCALL */ + +/* 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_DRBG_FAIL 11 +#define NTRU_MGF1_FAIL 12 + +/* function declarations */ + +/* ntru_crypto_ntru_encrypt + * + * Implements NTRU encryption (SVES) for the parameter set specified in + * the public key blob. + * + * Before invoking this function, a DRBG must be instantiated using + * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that + * instantiation the requested security strength must be at least as large + * as the security strength of the NTRU parameter set being used. + * Failure to instantiate the DRBG with the proper security strength will + * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH. + * + * The required minimum size of the output ciphertext buffer (ct) may be + * queried by invoking this function with ct = NULL. In this case, no + * encryption is performed, NTRU_OK is returned, and the required minimum + * size for ct is returned in ct_len. + * + * When ct != NULL, at invocation *ct_len must be the size of the ct buffer. + * Upon return it is the actual size of the ciphertext. + * + * Returns NTRU_OK if successful. + * Returns NTRU_DRBG_FAIL if the DRBG handle is invalid. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL. + * Returns NTRU_BAD_LENGTH if a length argument (pubkey_blob_len or pt_len) is + * zero, or if pt_len exceeds the maximum plaintext length for the parameter set. + * Returns NTRU_BAD_PUBLIC_KEY if the public-key blob is invalid + * (unknown format, corrupt, bad length). + * Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. + */ + +NTRUCALL +ntru_crypto_ntru_encrypt( + ntru_drbg_t *drbg , /* in - handle for DRBG */ + uint16_t pubkey_blob_len, /* in - no. of octets in public key + blob */ + uint8_t const *pubkey_blob, /* in - pointer to public key */ + uint16_t pt_len, /* in - no. of octets in plaintext */ + uint8_t const *pt, /* in - pointer to plaintext */ + uint16_t *ct_len, /* in/out - no. of octets in ct, addr for + no. of octets in ciphertext */ + uint8_t *ct); /* out - address for ciphertext */ + + +/* 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_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 +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 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. + * 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_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. + */ + +NTRUCALL +ntru_crypto_ntru_encrypt_keygen( + ntru_drbg_t *drbg, /* 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 */ +#endif /* NTRU_CRYPTO_H */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c new file mode 100644 index 000000000..3d6dfde41 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c @@ -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; + } +} + + diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h new file mode 100644 index 000000000..1c4b35b24 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h @@ -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 */ + + 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 new file mode 100644 index 000000000..dba81915a --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c @@ -0,0 +1,1034 @@ +/****************************************************************************** + * NTRU Cryptography Reference Source Code + * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. + * + * ntru_crypto_ntru_encrypt.c is a component of ntru-crypto. + * + * Copyright (C) 2009-2013 Security Innovation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *****************************************************************************/ + +/****************************************************************************** + * + * File: ntru_crypto_ntru_encrypt.c + * + * Contents: Routines implementing NTRUEncrypt encryption and decryption and + * key generation. + * + *****************************************************************************/ + + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "ntru_crypto.h" +#include "ntru_crypto_ntru_encrypt_param_sets.h" +#include "ntru_crypto_ntru_encrypt_key.h" +#include "ntru_crypto_ntru_convert.h" +#include "ntru_crypto_ntru_poly.h" +# +#include "ntru_trits.h" +#include "ntru_poly.h" + +/* ntru_crypto_ntru_encrypt + * + * Implements NTRU encryption (SVES) for the parameter set specified in + * the public key blob. + * + * Before invoking this function, a DRBG must be instantiated using + * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that + * instantiation the requested security strength must be at least as large + * as the security strength of the NTRU parameter set being used. + * Failure to instantiate the DRBG with the proper security strength will + * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH. + * + * The required minimum size of the output ciphertext buffer (ct) may be + * queried by invoking this function with ct = NULL. In this case, no + * encryption is performed, NTRU_OK is returned, and the required minimum + * size for ct is returned in ct_len. + * + * When ct != NULL, at invocation *ct_len must be the size of the ct buffer. + * Upon return it is the actual size of the ciphertext. + * + * Returns NTRU_OK if successful. + * Returns NTRU_DRBG_FAIL if the DRBG handle is invalid. + * Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL. + * Returns NTRU_BAD_LENGTH if a length argument (pubkey_blob_len or pt_len) is + * zero, or if pt_len exceeds the maximum plaintext length for the parameter set. + * Returns NTRU_BAD_PUBLIC_KEY if the public-key blob is invalid + * (unknown format, corrupt, bad length). + * Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small. + * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap. + */ + +uint32_t +ntru_crypto_ntru_encrypt( + ntru_drbg_t *drbg, /* in - handle of DRBG */ + uint16_t pubkey_blob_len, /* in - no. of octets in public key + blob */ + uint8_t const *pubkey_blob, /* in - pointer to public key */ + uint16_t pt_len, /* in - no. of octets in plaintext */ + uint8_t const *pt, /* in - pointer to plaintext */ + uint16_t *ct_len, /* in/out - no. of octets in ct, addr for + no. of octets in ciphertext */ + uint8_t *ct) /* out - address for ciphertext */ +{ + NTRU_ENCRYPT_PARAM_SET *params = NULL; + uint8_t const *pubkey_packed = NULL; + uint8_t pubkey_pack_type = 0x00; + uint16_t packed_ct_len; + size_t scratch_buf_len; + uint32_t dr; + uint32_t dr1 = 0; + uint32_t dr2 = 0; + uint32_t dr3 = 0; + uint16_t ring_mult_tmp_len; + int16_t m1 = 0; + uint16_t *scratch_buf = NULL; + uint16_t *ringel_buf = NULL; + uint8_t *b_buf = NULL; + uint8_t *tmp_buf = NULL; + bool msg_rep_good = FALSE; + hash_algorithm_t hash_algid; + uint16_t mprime_len = 0; + uint16_t mod_q_mask; + uint32_t result = NTRU_OK; + ntru_trits_t *mask; + uint8_t *mask_trits; + chunk_t seed; + ntru_poly_t *r_poly; + + /* check for bad parameters */ + + if (!pubkey_blob || !pt || !ct_len) + { + return NTRU_BAD_PARAMETER; + } + if ((pubkey_blob_len == 0) || (pt_len == 0)) + { + return NTRU_BAD_LENGTH; + } + + /* get a pointer to the parameter-set parameters, the packing type for + * the public key, and a pointer to the packed public key + */ + + if (!ntru_crypto_ntru_encrypt_key_parse(TRUE /* pubkey */, pubkey_blob_len, + pubkey_blob, &pubkey_pack_type, + NULL, ¶ms, &pubkey_packed, + NULL)) + { + return NTRU_BAD_PUBLIC_KEY; + } + + /* return the ciphertext size if requested */ + + packed_ct_len = (params->N * params->q_bits + 7) >> 3; + if (!ct) + { + *ct_len = packed_ct_len; + return NTRU_OK; + } + + /* check the ciphertext buffer size */ + + if (*ct_len < packed_ct_len) + { + return NTRU_BUFFER_TOO_SMALL; + } + + /* check the plaintext length */ + + if (pt_len > params->m_len_max) + { + return NTRU_BAD_LENGTH; + } + + /* allocate memory for all operations */ + + if (params->is_product_form) + { + ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */ + dr1 = params->dF_r & 0xff; + dr2 = (params->dF_r >> 8) & 0xff; + dr3 = (params->dF_r >> 16) & 0xff; + dr = dr1 + dr2 + dr3; + } + else + { + ring_mult_tmp_len = params->N; /* N 16-bit word buffer */ + dr = params->dF_r; + } + scratch_buf_len = (ring_mult_tmp_len << 1) + + /* X-byte temp buf for ring mult and + other intermediate results */ + (params->N << 1) + /* 2N-byte buffer for ring elements + and overflow from temp buffer */ + (dr << 2) + /* buffer for r indices */ + params->sec_strength_len; + /* buffer for b */ + scratch_buf = malloc(scratch_buf_len); + if (!scratch_buf) + { + return NTRU_OUT_OF_MEMORY; + } + ringel_buf = scratch_buf + ring_mult_tmp_len; + b_buf = (uint8_t *)(ringel_buf + params->N); + tmp_buf = (uint8_t *)scratch_buf; + + /* set hash algorithm based on security strength */ + hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256; + + /* set constants */ + mod_q_mask = params->q - 1; + + /* loop until a message representative with proper weight is achieved */ + + do { + uint8_t *ptr = tmp_buf; + + /* get b */ + if (drbg->generate(drbg, params->sec_strength_len * BITS_PER_BYTE, + params->sec_strength_len, b_buf)) + { + result = NTRU_OK; + } + else + { + result = NTRU_FAIL; + } + + if (result == NTRU_OK) + { + + /* form sData (OID || m || b || hTrunc) */ + memcpy(ptr, params->OID, 3); + ptr += 3; + memcpy(ptr, pt, pt_len); + ptr += pt_len; + memcpy(ptr, b_buf, params->sec_strength_len); + ptr += params->sec_strength_len; + memcpy(ptr, pubkey_packed, params->sec_strength_len); + ptr += params->sec_strength_len; + + DBG2(DBG_LIB, "generate polynomial r"); + + seed = chunk_create(tmp_buf, ptr - tmp_buf); + r_poly = ntru_poly_create_from_seed(hash_algid, seed, params->c_bits, + params->N, params->q, + params->dF_r, params->dF_r, + params->is_product_form); + if (!r_poly) + { + result = NTRU_MGF1_FAIL; + } + } + + if (result == NTRU_OK) + { + uint16_t pubkey_packed_len; + + /* unpack the public key */ + assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS); + pubkey_packed_len = (params->N * params->q_bits + 7) >> 3; + ntru_octets_2_elements(pubkey_packed_len, pubkey_packed, + params->q_bits, ringel_buf); + + /* form R = h * r */ + r_poly->ring_mult(r_poly, ringel_buf, ringel_buf); + r_poly->destroy(r_poly); + + /* form R mod 4 */ + ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf); + + /* form mask */ + seed = chunk_create(tmp_buf, (params->N + 3)/4); + mask = ntru_trits_create(params->N, hash_algid, seed); + if (!mask) + { + result = NTRU_MGF1_FAIL; + } + } + + if (result == NTRU_OK) + { + uint8_t *Mtrin_buf = tmp_buf + params->N; + uint8_t *M_buf = Mtrin_buf + params->N - + (params->sec_strength_len + params->m_len_len + + params->m_len_max + 2); + uint16_t i; + + /* form the padded message M */ + ptr = M_buf; + memcpy(ptr, b_buf, params->sec_strength_len); + ptr += params->sec_strength_len; + if (params->m_len_len == 2) + *ptr++ = (uint8_t)((pt_len >> 8) & 0xff); + *ptr++ = (uint8_t)(pt_len & 0xff); + memcpy(ptr, pt, pt_len); + ptr += pt_len; + + /* add an extra zero byte in case without it the bit string + * is not a multiple of 3 bits and therefore might not be + * able to produce enough trits + */ + + memset(ptr, 0, params->m_len_max - pt_len + 2); + + /* convert M to trits (Mbin to Mtrin) */ + mprime_len = params->N; + if (params->is_product_form) + { + --mprime_len; + } + + ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf); + mask_trits = mask->get_trits(mask); + + /* form the msg representative m' by adding Mtrin to mask, mod p */ + if (params->is_product_form) + { + for (i = 0; i < mprime_len; i++) + { + tmp_buf[i] = mask_trits[i] + Mtrin_buf[i]; + if (tmp_buf[i] >= 3) + { + tmp_buf[i] -= 3; + } + if (tmp_buf[i] == 1) + { + ++m1; + } + else if (tmp_buf[i] == 2) + { + --m1; + } + } + } + else + { + for (i = 0; i < mprime_len; i++) + { + tmp_buf[i] = mask_trits[i] + Mtrin_buf[i]; + if (tmp_buf[i] >= 3) + { + tmp_buf[i] -= 3; + } + } + } + mask->destroy(mask); + + /* check that message representative meets minimum weight + * requirements + */ + + if (params->is_product_form) + msg_rep_good = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) : + (bool)( m1 <= params->min_msg_rep_wt); + else + msg_rep_good = ntru_poly_check_min_weight(mprime_len, tmp_buf, + params->min_msg_rep_wt); + msg_rep_good = TRUE; + } + } while ((result == NTRU_OK) && !msg_rep_good); + + if (result == NTRU_OK) + { + uint16_t i; + + /* form ciphertext e by adding m' to R mod q */ + + for (i = 0; i < mprime_len; i++) { + if (tmp_buf[i] == 1) + ringel_buf[i] = (ringel_buf[i] + 1) & mod_q_mask; + else if (tmp_buf[i] == 2) + ringel_buf[i] = (ringel_buf[i] - 1) & mod_q_mask; + } + if (params->is_product_form) + ringel_buf[i] = (ringel_buf[i] - m1) & mod_q_mask; + + /* pack ciphertext */ + ntru_elements_2_octets(params->N, ringel_buf, params->q_bits, ct); + *ct_len = packed_ct_len; + } + + /* cleanup */ + memset(scratch_buf, 0, scratch_buf_len); + free(scratch_buf); + + return result; +} + + +/* ntru_crypto_ntru_decrypt + * + * Implements NTRU decryption (SVES) for the parameter set specified in + * the private key blob. + * + * The maximum size of the output plaintext may be queried by invoking + * this function with pt = NULL. In this case, no decryption is performed, + * NTRU_OK is returned, and the maximum size the plaintext could be is + * returned in pt_len. + * Note that until the decryption is performed successfully, the actual size + * of the resulting plaintext cannot be known. + * + * When pt != NULL, at invocation *pt_len must be the size of the pt buffer. + * Upon return it is the actual size of the plaintext. + * + * Returns NTRU_OK if successful. + * Returns NTRU_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 +ntru_crypto_ntru_decrypt( + uint16_t privkey_blob_len, /* in - no. of octets in private key + blob */ + uint8_t const *privkey_blob, /* in - pointer to private key */ + uint16_t ct_len, /* in - no. of octets in ciphertext */ + uint8_t const *ct, /* in - pointer to ciphertext */ + uint16_t *pt_len, /* in/out - no. of octets in pt, addr for + no. of octets in plaintext */ + uint8_t *pt) /* out - address for plaintext */ +{ + NTRU_ENCRYPT_PARAM_SET *params = NULL; + uint8_t const *privkey_packed = NULL; + uint8_t const *pubkey_packed = NULL; + uint8_t privkey_pack_type = 0x00; + uint8_t pubkey_pack_type = 0x00; + size_t scratch_buf_len; + uint32_t dF_r; + uint32_t dF_r1 = 0; + uint32_t dF_r2 = 0; + uint32_t dF_r3 = 0; + uint16_t ring_mult_tmp_len; + int16_t m1 = 0; + uint16_t *scratch_buf = NULL; + uint16_t *ringel_buf1 = NULL; + uint16_t *ringel_buf2 = NULL; + uint16_t *i_buf = NULL; + uint8_t *m_buf = NULL; + uint8_t *tmp_buf = NULL; + uint8_t *Mtrin_buf = NULL; + uint8_t *M_buf = NULL; + uint8_t *ptr = NULL; + hash_algorithm_t hash_algid; + uint16_t cmprime_len; + uint16_t mod_q_mask; + uint16_t q_mod_p; + uint16_t cm_len = 0; + uint16_t num_zeros; + uint16_t i; + bool decryption_ok = TRUE; + uint32_t result = NTRU_OK; + ntru_trits_t *mask; + uint8_t *mask_trits; + chunk_t seed; + ntru_poly_t *F_poly, *r_poly; + + /* check for bad parameters */ + 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 */, + privkey_blob_len, + privkey_blob, &pubkey_pack_type, + &privkey_pack_type, ¶ms, + &pubkey_packed, &privkey_packed)) + { + return NTRU_BAD_PRIVATE_KEY; + } + + /* return the max plaintext size if requested */ + + if (!pt) + { + *pt_len = params->m_len_max; + return NTRU_OK; + } + + /* cannot check the plaintext buffer size until after the plaintext + * is derived, if we allow plaintext buffers only as large as the + * actual plaintext + */ + + /* check the ciphertext length */ + + if (ct_len != (params->N * params->q_bits + 7) >> 3) + { + return NTRU_BAD_LENGTH; + } + + /* allocate memory for all operations */ + + if (params->is_product_form) + { + ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */ + dF_r1 = params->dF_r & 0xff; + dF_r2 = (params->dF_r >> 8) & 0xff; + dF_r3 = (params->dF_r >> 16) & 0xff; + dF_r = dF_r1 + dF_r2 + dF_r3; + } else { + ring_mult_tmp_len = params->N; /* N 16-bit word buffer */ + dF_r = params->dF_r; + } + scratch_buf_len = (ring_mult_tmp_len << 1) + + /* X-byte temp buf for ring mult and + other intermediate results */ + (params->N << 2) + /* 2 2N-byte bufs for ring elements + and overflow from temp buffer */ + (dF_r << 2) + /* buffer for F, r indices */ + params->m_len_max; /* buffer for plaintext */ + scratch_buf = malloc(scratch_buf_len); + if (!scratch_buf) + { + return NTRU_OUT_OF_MEMORY; + } + ringel_buf1 = scratch_buf + ring_mult_tmp_len; + ringel_buf2 = ringel_buf1 + params->N; + i_buf = ringel_buf2 + params->N; + m_buf = (uint8_t *)(i_buf + (dF_r << 1)); + tmp_buf = (uint8_t *)scratch_buf; + Mtrin_buf = (uint8_t *)ringel_buf1; + M_buf = Mtrin_buf + params->N; + + /* set hash algorithm based on security strength */ + 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) + { + ntru_packed_trits_2_indices(privkey_packed, params->N, i_buf, + i_buf + dF_r); + + } + else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES) + { + ntru_octets_2_elements( + (((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3, + privkey_packed, params->N_bits, i_buf); + + } + else + { + assert(FALSE); + } + + /* form cm': + * F * e + * A = e * (1 + pF) mod q = e + pFe mod q + * a = A in the range [-q/2, q/2) + * cm' = a mod p + */ + F_poly = ntru_poly_create_from_data(i_buf, params->N, params->q, + params->dF_r, params->dF_r, + params->is_product_form); + F_poly->ring_mult(F_poly, ringel_buf2, ringel_buf1); + F_poly->destroy(F_poly); + + cmprime_len = params->N; + if (params->is_product_form) + { + --cmprime_len; + for (i = 0; i < cmprime_len; i++) + { + ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask; + if (ringel_buf1[i] >= (params->q >> 1)) + { + ringel_buf1[i] = ringel_buf1[i] - q_mod_p; + } + Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3); + if (Mtrin_buf[i] == 1) + { + ++m1; + } + else if (Mtrin_buf[i] == 2) + { + --m1; + } + } + } + else + { + for (i = 0; i < cmprime_len; i++) + { + ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask; + if (ringel_buf1[i] >= (params->q >> 1)) + { + ringel_buf1[i] = ringel_buf1[i] - q_mod_p; + } + Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3); + } + } + + /* check that the candidate message representative meets minimum weight + * requirements + */ + + if (params->is_product_form) + { + decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) : + (bool)( m1 <= params->min_msg_rep_wt); + } + else + { + decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf, + params->min_msg_rep_wt); + } + + /* form cR = e - cm' mod q */ + for (i = 0; i < cmprime_len; i++) + { + if (Mtrin_buf[i] == 1) + { + ringel_buf2[i] = (ringel_buf2[i] - 1) & mod_q_mask; + } + else if (Mtrin_buf[i] == 2) + { + ringel_buf2[i] = (ringel_buf2[i] + 1) & mod_q_mask; + } + } + if (params->is_product_form) + { + ringel_buf2[i] = (ringel_buf2[i] + m1) & mod_q_mask; + } + + /* form cR mod 4 */ + ntru_coeffs_mod4_2_octets(params->N, ringel_buf2, tmp_buf); + + /* form mask */ + seed = chunk_create(tmp_buf, (params->N + 3)/4); + mask = ntru_trits_create(params->N, hash_algid, seed); + if (!mask) + { + result = NTRU_MGF1_FAIL; + } + else + { + mask_trits = mask->get_trits(mask); + + /* form cMtrin by subtracting mask from cm', mod p */ + for (i = 0; i < cmprime_len; i++) + { + Mtrin_buf[i] = Mtrin_buf[i] - mask_trits[i]; + if (Mtrin_buf[i] >= 3) + { + Mtrin_buf[i] += 3; + } + } + mask->destroy(mask); + + if (params->is_product_form) + + /* set the last trit to zero since that's what it was, and + * because it can't be calculated from (cm' - mask) since + * we don't have the correct value for the last cm' trit + */ + + Mtrin_buf[i] = 0; + + /* convert cMtrin to cM (Mtrin to Mbin) */ + + if (!ntru_trits_2_bits(Mtrin_buf, params->N, M_buf)) + decryption_ok = FALSE; + + /* validate the padded message cM and copy cm to m_buf */ + + ptr = M_buf + params->sec_strength_len; + if (params->m_len_len == 2) + cm_len = (uint16_t)(*ptr++) << 16; + cm_len |= (uint16_t)(*ptr++); + if (cm_len > params->m_len_max) { + cm_len = params->m_len_max; + decryption_ok = FALSE; + } + memcpy(m_buf, ptr, cm_len); + ptr += cm_len; + num_zeros = params->m_len_max - cm_len + 1; + for (i = 0; i < num_zeros; i++) { + if (ptr[i] != 0) + decryption_ok = FALSE; + } + + /* form sData (OID || m || b || hTrunc) */ + + ptr = tmp_buf; + memcpy(ptr, params->OID, 3); + ptr += 3; + memcpy(ptr, m_buf, cm_len); + ptr += cm_len; + memcpy(ptr, M_buf, params->sec_strength_len); + ptr += params->sec_strength_len; + memcpy(ptr, pubkey_packed, params->sec_strength_len); + ptr += params->sec_strength_len; + + /* generate cr */ + DBG2(DBG_LIB, "generate polynomial r"); + + seed = chunk_create(tmp_buf, ptr - tmp_buf); + r_poly = ntru_poly_create_from_seed(hash_algid, seed, params->c_bits, + params->N, params->q, + params->dF_r, params->dF_r, + params->is_product_form); + if (!r_poly) + { + result = NTRU_MGF1_FAIL; + } + } + + if (result == NTRU_OK) + { + /* unpack the public key */ + { + uint16_t pubkey_packed_len; + + assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS); + pubkey_packed_len = (params->N * params->q_bits + 7) >> 3; + ntru_octets_2_elements(pubkey_packed_len, pubkey_packed, + params->q_bits, ringel_buf1); + } + + /* form cR' = h * cr */ + r_poly->ring_mult(r_poly, ringel_buf1, ringel_buf1); + r_poly->destroy(r_poly); + + /* compare cR' to cR */ + for (i = 0; i < params->N; i++) + { + if (ringel_buf1[i] != ringel_buf2[i]) + { + decryption_ok = FALSE; + } + } + + /* output plaintext and plaintext length */ + if (decryption_ok) + { + if (*pt_len < cm_len) + { + return NTRU_BUFFER_TOO_SMALL; + } + memcpy(pt, m_buf, cm_len); + *pt_len = cm_len; + } + } + + /* cleanup */ + memset(scratch_buf, 0, scratch_buf_len); + free(scratch_buf); + + if (!decryption_ok) + { + return NTRU_FAIL; + } + + return result; +} + + +/* ntru_crypto_ntru_encrypt_keygen + * + * Implements key generation for NTRUEncrypt for the parameter set specified. + * + * 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_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. + */ + +uint32_t +ntru_crypto_ntru_encrypt_keygen( + ntru_drbg_t *drbg, /* in - handle of DRBG */ + NTRU_ENCRYPT_PARAM_SET_ID param_set_id, /* in - parameter set ID */ + uint16_t *pubkey_blob_len, /* in/out - no. of octets in + pubkey_blob, addr + for no. of octets + in pubkey_blob */ + uint8_t *pubkey_blob, /* out - address for + public key blob */ + uint16_t *privkey_blob_len, /* in/out - no. of octets in + privkey_blob, addr + for no. of octets + in privkey_blob */ + uint8_t *privkey_blob) /* out - address for + private key blob */ +{ + NTRU_ENCRYPT_PARAM_SET *params = NULL; + uint16_t public_key_blob_len; + uint16_t private_key_blob_len; + uint8_t pubkey_pack_type; + uint8_t privkey_pack_type; + size_t scratch_buf_len; + uint32_t dF; + uint32_t dF1 = 0; + uint32_t dF2 = 0; + uint32_t dF3 = 0; + uint16_t *scratch_buf = NULL; + uint16_t *ringel_buf1 = NULL; + uint16_t *ringel_buf2 = NULL; + uint8_t *tmp_buf = NULL; + uint16_t mod_q_mask; + hash_algorithm_t hash_algid; + uint16_t seed_len; + chunk_t seed; + uint32_t result = NTRU_OK; + ntru_poly_t *F_poly = NULL; + ntru_poly_t *g_poly = NULL; + uint16_t *F_indices; + + /* get a pointer to the parameter-set parameters */ + + if ((params = ntru_encrypt_get_params_with_id(param_set_id)) == NULL) + { + return NTRU_INVALID_PARAMETER_SET; + } + + /* check for bad parameters */ + + if (!pubkey_blob_len || !privkey_blob_len) + { + return NTRU_BAD_PARAMETER; + } + + /* get public and private key packing types and blob lengths */ + + ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type, + &public_key_blob_len, + &privkey_pack_type, + &private_key_blob_len); + + /* return the pubkey_blob size and/or privkey_blob size if requested */ + + if (!pubkey_blob || !privkey_blob) + { + if (!pubkey_blob) + *pubkey_blob_len = public_key_blob_len; + if (!privkey_blob) + *privkey_blob_len = private_key_blob_len; + return NTRU_OK; + } + + /* check size of output buffers */ + + if ((*pubkey_blob_len < public_key_blob_len) || + (*privkey_blob_len < private_key_blob_len)) + { + 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; + dF3 = (params->dF_r >> 16) & 0xff; + dF = dF1 + dF2 + dF3; + } else { + dF = params->dF_r; + } + + scratch_buf_len = (params->N * 8) + /* 4N-byte temp buffer for ring inv + and other intermediate results, + 2N-byte buffer for f, g indices + and overflow from temp buffer, + 2N-byte buffer for f^-1 */ + (dF << 2); /* buffer for F indices */ + scratch_buf = malloc(scratch_buf_len); + if (!scratch_buf) + { + return NTRU_OUT_OF_MEMORY; + } + ringel_buf1 = scratch_buf + (params->N << 1); + ringel_buf2 = ringel_buf1 + params->N; + tmp_buf = (uint8_t *)scratch_buf; + + /* set hash algorithm and seed length based on security strength */ + if (params->sec_strength_len <= 20) + { + hash_algid = HASH_SHA1; + } + else + { + hash_algid = HASH_SHA256; + } + seed_len = params->sec_strength_len + 8; + + /* set constants */ + + mod_q_mask = params->q - 1; + + /* get random bytes for seed for generating trinary F + * as a list of indices + */ + + if (drbg->generate(drbg, params->sec_strength_len * BITS_PER_BYTE, + seed_len, tmp_buf)) + { + result = NTRU_OK; + } + else + { + result = NTRU_DRBG_FAIL; + } + + if (result == NTRU_OK) + { + DBG2(DBG_LIB, "generate polynomial F"); + + seed = chunk_create(tmp_buf, seed_len); + F_poly = ntru_poly_create_from_seed(hash_algid, seed, params->c_bits, + params->N, params->q, + params->dF_r, params->dF_r, + params->is_product_form); + if (!F_poly) + { + result = NTRU_MGF1_FAIL; + } + } + + if (result == NTRU_OK) + { + int i; + + F_poly->get_array(F_poly, ringel_buf1); + + /* form f = 1 + pF */ + for (i = 0; i < params->N; i++) + { + ringel_buf1[i] = (ringel_buf1[i] * 3) & mod_q_mask; + } + ringel_buf1[0] = (ringel_buf1[0] + 1) & mod_q_mask; + + /* find f^-1 in (Z/qZ)[X]/(X^N - 1) */ + if (!ntru_ring_inv(ringel_buf1, params->N, params->q, + scratch_buf, ringel_buf2)) + { + result = NTRU_FAIL; + } + } + + if (result == NTRU_OK) + { + + /* get random bytes for seed for generating trinary polynomial g + * as a list of indices + */ + if (!drbg->generate(drbg, params->sec_strength_len * BITS_PER_BYTE, + seed_len, tmp_buf)) + { + result = NTRU_DRBG_FAIL; + } + } + + if (result == NTRU_OK) + { + DBG2(DBG_LIB, "generate polynomial g"); + + seed = chunk_create(tmp_buf, seed_len); + g_poly = ntru_poly_create_from_seed(hash_algid, seed, params->c_bits, + params->N, params->q, + params->dg + 1, params->dg, FALSE); + if (!g_poly) + { + result = NTRU_MGF1_FAIL; + } + } + + if (result == NTRU_OK) + { + uint16_t i; + + /* compute h = p * (f^-1 * g) mod q */ + g_poly->ring_mult(g_poly, ringel_buf2, ringel_buf2); + g_poly->destroy(g_poly); + + for (i = 0; i < params->N; i++) + { + ringel_buf2[i] = (ringel_buf2[i] * 3) & mod_q_mask; + } + + /* create public key blob */ + ntru_crypto_ntru_encrypt_key_create_pubkey_blob(params, ringel_buf2, + pubkey_pack_type, + pubkey_blob); + *pubkey_blob_len = public_key_blob_len; + + /* create private key blob */ + F_indices = F_poly->get_indices(F_poly); + ntru_crypto_ntru_encrypt_key_create_privkey_blob(params, ringel_buf2, + F_indices, + privkey_pack_type, + tmp_buf, privkey_blob); + *privkey_blob_len = private_key_blob_len; + } + + /* cleanup */ + DESTROY_IF(F_poly); + memset(scratch_buf, 0, scratch_buf_len); + free(scratch_buf); + + return result; +} diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c new file mode 100644 index 000000000..90baaadf3 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c @@ -0,0 +1,360 @@ +/****************************************************************************** + * 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_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; + } +} + + diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h new file mode 100644 index 000000000..6734f2a4c --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h @@ -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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c new file mode 100644 index 000000000..5ddf91d2a --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c @@ -0,0 +1,384 @@ +/****************************************************************************** + * 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 */ + 11, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 9, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 11, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 13, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 12, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 11, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 10, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 12, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 11, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 12, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 13, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 13, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 11, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 9, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 11, /* c */ + 1, /* lLen */ + }, + + { + 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 */ + 13, /* c */ + 1, /* lLen */ + }, + +}; + +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; +} + diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h new file mode 100644 index 000000000..e5e977a0e --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * 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" + +/* 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 */ + 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 */ +} 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 */ + +#endif /* NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H */ + diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c new file mode 100644 index 000000000..8e4eede87 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c @@ -0,0 +1,242 @@ +/****************************************************************************** + * NTRU Cryptography Reference Source Code + * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. + * + * ntru_crypto_ntru_poly.c is a component of ntru-crypto. + * + * Copyright (C) 2009-2013 Security Innovation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *****************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include "ntru_crypto_ntru_poly.h" + +/* ntru_poly_check_min_weight + * + * Checks that the number of 0, +1, and -1 trinary ring elements meet or exceed + * a minimum weight. + */ + +bool +ntru_poly_check_min_weight( + uint16_t num_els, /* in - degree of polynomial */ + uint8_t *ringels, /* in - pointer to trinary ring elements */ + uint16_t min_wt) /* in - minimum weight */ +{ + uint16_t wt[3]; + uint16_t i; + + wt[0] = wt[1] = wt[2] = 0; + for (i = 0; i < num_els; i++) { + ++wt[ringels[i]]; + } + if ((wt[0] < min_wt) || (wt[1] < min_wt) || (wt[2] < min_wt)) { + return FALSE; + } + return TRUE; +} + +/* 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; + + /* 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; + + /* 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; + + +} + + 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 new file mode 100644 index 000000000..1e9d467ed --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h @@ -0,0 +1,96 @@ +/****************************************************************************** + * NTRU Cryptography Reference Source Code + * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. + * + * ntru_crypto_ntru_poly.h is a component of ntru-crypto. + * + * Copyright (C) 2009-2013 Security Innovation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *****************************************************************************/ + +/****************************************************************************** + * + * File: ntru_crypto_ntru_poly.h + * + * Contents: Public header file for generating and operating on polynomials + * in the NTRU algorithm. + * + *****************************************************************************/ + + +#ifndef NTRU_CRYPTO_NTRU_POLY_H +#define NTRU_CRYPTO_NTRU_POLY_H + + +#include "ntru_crypto.h" + +#include <crypto/hashers/hasher.h> + + +/* function declarations */ + +/* ntru_poly_check_min_weight + * + * Checks that the number of 0, +1, and -1 trinary ring elements meet or exceed + * a minimum weight. + */ + +extern bool +ntru_poly_check_min_weight( + uint16_t num_els, /* in - degree of polynomial */ + uint8_t *ringels, /* in - pointer to trinary ring elements */ + uint16_t min_wt); /* in - minimum weight */ + +/* 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 */ diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.c b/src/libstrongswan/plugins/ntru/ntru_drbg.c new file mode 100644 index 000000000..181a58939 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_drbg.c @@ -0,0 +1,279 @@ +/* + * 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_drbg.h" + +#include <utils/debug.h> +#include <utils/test.h> + +#define MAX_STRENGTH_BITS 256 +#define MAX_DRBG_REQUESTS 0xfffffffe + +typedef struct private_ntru_drbg_t private_ntru_drbg_t; + +/** + * Private data of an ntru_drbg_t object. + */ +struct private_ntru_drbg_t { + /** + * Public ntru_drbg_t interface. + */ + ntru_drbg_t public; + + /** + * Security strength in bits of the DRBG + */ + u_int32_t strength; + + /** + * Number of requests for pseudorandom bits + */ + u_int32_t reseed_counter; + + /** + * Maximum number of requests for pseudorandom bits + */ + u_int32_t max_requests; + + /** + * True entropy source + */ + rng_t *entropy; + + /** + * HMAC-SHA256 + */ + signer_t *hmac; + + /** + * Internal state of HMAC-SHA256: key + */ + chunk_t key; + + /** + * Internal state of HMAC-SHA256: value + */ + chunk_t value; + +}; + +/** + * Update the internal state of the HMAC_DRBG + */ +static bool update(private_ntru_drbg_t *this, chunk_t data) +{ + chunk_t ch_00 = chunk_from_chars(0x00); + chunk_t ch_01 = chunk_from_chars(0x01); + + if (!this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, NULL) || + !this->hmac->get_signature(this->hmac, ch_00, NULL) || + !this->hmac->get_signature(this->hmac, data, this->key.ptr) || + !this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, + this->value.ptr)) + { + return FALSE; + } + + if (data.len > 0) + { + if (!this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, NULL) || + !this->hmac->get_signature(this->hmac, ch_01, NULL) || + !this->hmac->get_signature(this->hmac, data, this->key.ptr) || + !this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, + this->value.ptr)) + { + return FALSE; + } + } + DBG4(DBG_LIB, "HMAC_DRBG V: %B", &this->value); + DBG4(DBG_LIB, "HMAC_DRBG K: %B", &this->key); + + return TRUE; +} + +METHOD(ntru_drbg_t, get_strength, u_int32_t, + private_ntru_drbg_t *this) +{ + return this->strength; +} + +METHOD(ntru_drbg_t, reseed, bool, + private_ntru_drbg_t *this) +{ + chunk_t seed; + + seed = chunk_alloc(this->strength / BITS_PER_BYTE); + DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed.len); + + if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr)) + { + chunk_free(&seed); + return FALSE; + } + if (!update(this, seed)) + { + chunk_free(&seed); + return FALSE; + } + chunk_clear(&seed); + this->reseed_counter = 1; + + return TRUE; +} + +METHOD(ntru_drbg_t, generate, bool, + private_ntru_drbg_t *this, u_int32_t strength, u_int32_t len, u_int8_t *out) +{ + size_t delta; + chunk_t output; + + DBG2(DBG_LIB, "DRBG generates %u pseudorandom bytes", len); + if (!out || len == 0) + { + return FALSE; + } + output = chunk_create(out, len); + + if (this->reseed_counter > this->max_requests) + { + if (!reseed(this)) + { + return FALSE; + } + } + while (len) + { + if (!this->hmac->get_signature(this->hmac, this->value, + this->value.ptr)) + { + return FALSE; + } + delta = min(len, this->value.len); + memcpy(out, this->value.ptr, delta); + len -= delta; + out += delta; + } + DBG4(DBG_LIB, "HMAC_DRBG Out: %B", &output); + + if (!update(this, chunk_empty)) + { + return FALSE; + } + this->reseed_counter++; + + return TRUE; +} + +METHOD(ntru_drbg_t, destroy, void, + private_ntru_drbg_t *this) +{ + this->hmac->destroy(this->hmac); + chunk_clear(&this->key); + chunk_clear(&this->value); + free(this); +} + +/* + * Described in header. + */ +ntru_drbg_t *ntru_drbg_create(u_int32_t strength, chunk_t pers_str, + rng_t *entropy) +{ + private_ntru_drbg_t *this; + chunk_t seed; + signer_t *hmac; + size_t entropy_len; + u_int32_t max_requests; + + if (strength > MAX_STRENGTH_BITS) + { + return NULL; + } + if (strength <= 112) + { + strength = 112; + } + else if (strength <= 128) + { + strength = 128; + } + else if (strength <= 192) + { + strength = 192; + } + else + { + strength = 256; + } + + hmac = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA2_256_256); + if (!hmac) + { + DBG1(DBG_LIB, "could not instantiate HMAC-SHA256"); + return NULL; + } + + max_requests = lib->settings->get_int(lib->settings, + "%s.plugins.ntru.max_drbg_requests", + MAX_DRBG_REQUESTS, lib->ns); + + INIT(this, + .public = { + .get_strength = _get_strength, + .reseed = _reseed, + .generate = _generate, + .destroy = _destroy, + }, + .strength = strength, + .entropy = entropy, + .hmac = hmac, + .key = chunk_alloc(hmac->get_key_size(hmac)), + .value = chunk_alloc(hmac->get_block_size(hmac)), + .max_requests = max_requests, + .reseed_counter = 1, + ); + + memset(this->key.ptr, 0x00, this->key.len); + memset(this->value.ptr, 0x01, this->value.len); + + entropy_len = (strength + strength/2) / BITS_PER_BYTE; + seed = chunk_alloc(entropy_len + pers_str.len); + DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", entropy_len); + + if (!this->entropy->get_bytes(this->entropy, entropy_len, seed.ptr)) + { + chunk_free(&seed); + destroy(this); + return NULL; + } + memcpy(seed.ptr + entropy_len, pers_str.ptr, pers_str.len); + DBG4(DBG_LIB, "seed: %B", &seed); + + if (!update(this, seed)) + { + chunk_free(&seed); + destroy(this); + return NULL; + } + chunk_clear(&seed); + + return &this->public; +} + +EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create); diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.h b/src/libstrongswan/plugins/ntru/ntru_drbg.h new file mode 100644 index 000000000..38ac718ae --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_drbg.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 <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_drbg ntru_drbg + * @{ @ingroup ntru_p + */ + +#ifndef NTRU_DRBG_H_ +#define NTRU_DRBG_H_ + +typedef struct ntru_drbg_t ntru_drbg_t; + +#include <library.h> + +/** + * Implements a HMAC Deterministic Random Bit Generator (HMAC_DRBG) + * compliant with NIST SP 800-90A + */ +struct ntru_drbg_t { + + /** + * Reseed the instantiated DRBG + * + * @return configured security strength in bits + */ + u_int32_t (*get_strength)(ntru_drbg_t *this); + + /** + * Reseed the instantiated DRBG + * + * @return TRUE if successful + */ + bool (*reseed)(ntru_drbg_t *this); + + /** + * Generate pseudorandom bytes. + * If the maximum number of requests has been reached, reseeding occurs + * + * @param strength requested security strength in bits + * @param len number of octets to generate + * @param out address of output buffer + * @return TRUE if successful + */ + bool (*generate)(ntru_drbg_t *this, u_int32_t strength, u_int32_t len, + u_int8_t *out); + + /** + * Uninstantiate and destroy the DRBG object + */ + void (*destroy)(ntru_drbg_t *this); +}; + +/** + * Create and instantiate a new DRBG objet. + * + * @param strength security strength in bits + * @param pers_str personalization string + * @param entropy entropy source to use + */ +ntru_drbg_t *ntru_drbg_create(u_int32_t strength, chunk_t pers_str, + rng_t *entropy); + +#endif /** NTRU_DRBG_H_ @}*/ + diff --git a/src/libstrongswan/plugins/ntru/ntru_ke.c b/src/libstrongswan/plugins/ntru/ntru_ke.c new file mode 100644 index 000000000..39fb261cd --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_ke.c @@ -0,0 +1,396 @@ +/* + * 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_drbg.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; +typedef struct param_set_t param_set_t; + +/** + * Defines an NTRU parameter set by ID or OID + */ +struct param_set_t { + NTRU_ENCRYPT_PARAM_SET_ID id; + char oid[3]; + char *name; +}; + +/* Best bandwidth and speed, no X9.98 compatibility */ +static param_set_t param_sets_optimum[] = { + { NTRU_EES401EP2, {0x00, 0x02, 0x10}, "ees401ep2" }, + { NTRU_EES439EP1, {0x00, 0x03, 0x10}, "ees439ep1" }, + { NTRU_EES593EP1, {0x00, 0x05, 0x10}, "ees593ep1" }, + { NTRU_EES743EP1, {0x00, 0x06, 0x10}, "ees743ep1" } +}; + +/* X9.98/IEEE 1363.1 parameter sets for best speed */ +static param_set_t param_sets_x9_98_speed[] = { + { NTRU_EES659EP1, {0x00, 0x02, 0x06}, "ees659ep1" }, + { NTRU_EES761EP1, {0x00, 0x03, 0x05}, "ees761ep1" }, + { NTRU_EES1087EP1, {0x00, 0x05, 0x05}, "ees1087ep1" }, + { NTRU_EES1499EP1, {0x00, 0x06, 0x05}, "ees1499ep1" } +}; + +/* X9.98/IEEE 1363.1 parameter sets for best bandwidth (smallest size) */ +static param_set_t param_sets_x9_98_bandwidth[] = { + { NTRU_EES401EP1, {0x00, 0x02, 0x04}, "ees401ep1" }, + { NTRU_EES449EP1, {0x00, 0x03, 0x03}, "ees449ep1" }, + { NTRU_EES677EP1, {0x00, 0x05, 0x03}, "ees677ep1" }, + { NTRU_EES1087EP2, {0x00, 0x06, 0x03}, "ees1087ep2" } +}; + +/* X9.98/IEEE 1363.1 parameter sets balancing speed and bandwidth */ +static param_set_t param_sets_x9_98_balance[] = { + { NTRU_EES541EP1, {0x00, 0x02, 0x05}, "ees541ep1" }, + { NTRU_EES613EP1, {0x00, 0x03, 0x04}, "ees613ep1" }, + { NTRU_EES887EP1, {0x00, 0x05, 0x04}, "ees887ep1" }, + { NTRU_EES1171EP1, {0x00, 0x06, 0x04}, "ees1171ep1" } +}; + +/** + * 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 + */ + param_set_t *param_set; + + /** + * 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; + + /** + * True Random Generator + */ + rng_t *entropy; + + /** + * Deterministic Random Bit Generator + */ + ntru_drbg_t *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) + { + *secret = chunk_empty; + 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 */ + if (value.len == 0) + { + DBG1(DBG_LIB, "empty NTRU ciphertext"); + return; + } + 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; + + /* check the NTRU public key format */ + if (value.len < 5 || value.ptr[0] != 1 || value.ptr[1] != 3) + { + DBG1(DBG_LIB, "received NTRU public key with invalid header"); + return; + } + if (!memeq(value.ptr + 2, this->param_set->oid, 3)) + { + DBG1(DBG_LIB, "received NTRU public key with wrong OID"); + return; + } + 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 (!this->drbg->generate(this->drbg, this->strength, + this->shared_secret.len, this->shared_secret.ptr)) + { + DBG1(DBG_LIB, "generation of shared secret failed"); + chunk_free(&this->shared_secret); + return; + } + this->computed = TRUE; + + /* 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); + + /* 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) +{ + this->drbg->destroy(this->drbg); + this->entropy->destroy(this->entropy); + 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; + param_set_t *param_sets, *param_set; + rng_t *entropy; + ntru_drbg_t *drbg; + char *parameter_set; + u_int32_t strength; + + parameter_set = lib->settings->get_str(lib->settings, + "%s.plugins.ntru.parameter_set", "optimum", lib->ns); + + if (streq(parameter_set, "x9_98_speed")) + { + param_sets = param_sets_x9_98_speed; + } + else if (streq(parameter_set, "x9_98_bandwidth")) + { + param_sets = param_sets_x9_98_bandwidth; + } + else if (streq(parameter_set, "x9_98_balance")) + { + param_sets = param_sets_x9_98_balance; + } + else + { + param_sets = param_sets_optimum; + } + + switch (group) + { + case NTRU_112_BIT: + strength = 112; + param_set = ¶m_sets[0]; + break; + case NTRU_128_BIT: + strength = 128; + param_set = ¶m_sets[1]; + break; + case NTRU_192_BIT: + strength = 192; + param_set = ¶m_sets[2]; + break; + case NTRU_256_BIT: + strength = 256; + param_set = ¶m_sets[3]; + break; + default: + return NULL; + } + DBG1(DBG_LIB, "%u bit %s NTRU parameter set %s selected", strength, + parameter_set, param_set->name); + + entropy = lib->crypto->create_rng(lib->crypto, RNG_TRUE); + if (!entropy) + { + DBG1(DBG_LIB, "could not attach entropy source for DRBG"); + return NULL; + } + + drbg = ntru_drbg_create(strength, chunk_from_str("IKE NTRU-KE"), entropy); + if (!drbg) + { + DBG1(DBG_LIB, "could not instantiate DRBG at %u bit security", strength); + entropy->destroy(entropy); + return NULL; + } + + 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 = param_set, + .strength = strength, + .entropy = entropy, + .drbg = drbg, + ); + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/ntru/ntru_ke.h b/src/libstrongswan/plugins/ntru/ntru_ke.h new file mode 100644 index 000000000..b8bbf5e54 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_ke.h @@ -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_ @}*/ + diff --git a/src/libstrongswan/plugins/ntru/ntru_mgf1.c b/src/libstrongswan/plugins/ntru/ntru_mgf1.c new file mode 100644 index 000000000..2338db208 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_mgf1.c @@ -0,0 +1,182 @@ +/* + * 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_mgf1.h" + +#include <crypto/hashers/hasher.h> +#include <utils/debug.h> +#include <utils/test.h> + +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 hash_len; + + hash_len = this->hasher->get_hash_size(this->hasher); + + 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; + } + + /* get the next or final mask block from the hash function */ + if (!this->hasher->get_hash(this->hasher, this->state, + (mask_len < hash_len) ? buf : mask)) + { + return FALSE; + } + if (mask_len < hash_len) + { + memcpy(mask, buf, mask_len); + return TRUE; + } + mask_len -= hash_len; + mask += hash_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 000000000..53e90412a --- /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 <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_mgf1 ntru_mgf1 + * @{ @ingroup ntru_p + */ + +#ifndef NTRU_MGF1_H_ +#define NTRU_MGF1_H_ + +typedef struct ntru_mgf1_t ntru_mgf1_t; + +#include <library.h> + +/** + * 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/plugins/ntru/ntru_plugin.c b/src/libstrongswan/plugins/ntru/ntru_plugin.c new file mode 100644 index 000000000..66be7c75b --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_plugin.c @@ -0,0 +1,83 @@ +/* + * 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> + +typedef struct private_ntru_plugin_t private_ntru_plugin_t; + +/** + * 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[]) +{ + static plugin_feature_t f[] = { + 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), + PLUGIN_DEPENDS(RNG, RNG_TRUE), + PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_SHA2_256_256), + PLUGIN_DEPENDS(HASHER, HASH_SHA256), + PLUGIN_SDEPEND(HASHER, HASH_SHA1) + }; + *features = f; + + return countof(f); +} + +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; +} diff --git a/src/libstrongswan/plugins/ntru/ntru_plugin.h b/src/libstrongswan/plugins/ntru/ntru_plugin.h new file mode 100644 index 000000000..187b83445 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_plugin.h @@ -0,0 +1,42 @@ +/* + * 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> + +typedef struct ntru_plugin_t ntru_plugin_t; + +/** + * Plugin implementing NTRU-base key exchange + */ +struct ntru_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** NTRU_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/ntru/ntru_poly.c b/src/libstrongswan/plugins/ntru/ntru_poly.c new file mode 100644 index 000000000..3f754f2a0 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_poly.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * Copyright (C) 2009-2013 Security Innovation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ntru_poly.h" +#include "ntru_mgf1.h" + +#include <utils/debug.h> +#include <utils/test.h> + +typedef struct private_ntru_poly_t private_ntru_poly_t; +typedef struct indices_len_t indices_len_t; + +/** + * Stores number of +1 and -1 coefficients + */ +struct indices_len_t { + int p; + int m; +}; + +/** + * Private data of an ntru_poly_t object. + */ +struct private_ntru_poly_t { + + /** + * Public ntru_poly_t interface. + */ + ntru_poly_t public; + + /** + * Ring dimension equal to the number of polynomial coefficients + */ + uint16_t N; + + /** + * Large modulus + */ + uint16_t q; + + /** + * Array containing the indices of the non-zero coefficients + */ + uint16_t *indices; + + /** + * Number of indices of the non-zero coefficients + */ + size_t num_indices; + + /** + * Number of sparse polynomials + */ + int num_polynomials; + + /** + * Number of nonzero coefficients for up to 3 sparse polynomials + */ + indices_len_t indices_len[3]; + +}; + +METHOD(ntru_poly_t, get_size, size_t, + private_ntru_poly_t *this) +{ + return this->num_indices; +} + +METHOD(ntru_poly_t, get_indices, uint16_t*, + private_ntru_poly_t *this) +{ + return this->indices; +} + +/** + * Multiplication of polynomial a with a sparse polynomial b given by + * the indices of its +1 and -1 coefficients results in polynomial c. + * This is a convolution operation + */ +static void ring_mult_i(uint16_t *a, indices_len_t len, uint16_t *indices, + uint16_t N, uint16_t mod_q_mask, uint16_t *t, + uint16_t *c) +{ + int i, j, k; + + /* initialize temporary array t */ + for (k = 0; k < N; k++) + { + t[k] = 0; + } + + /* t[(i+k)%N] = sum i=0 through N-1 of a[i], for b[k] = -1 */ + for (j = len.p; j < len.p + len.m; j++) + { + k = indices[j]; + for (i = 0; k < N; ++i, ++k) + { + t[k] += a[i]; + } + for (k = 0; i < N; ++i, ++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 < len.p; j++) + { + k = indices[j]; + for (i = 0; k < N; ++i, ++k) + { + t[k] += a[i]; + } + for (k = 0; i < N; ++i, ++k) + { + t[k] += a[i]; + } + } + + /* c = (a * b) mod q */ + for (k = 0; k < N; k++) + { + c[k] = t[k] & mod_q_mask; + } +} + +METHOD(ntru_poly_t, get_array, void, + private_ntru_poly_t *this, uint16_t *array) +{ + uint16_t *t, *bi; + uint16_t mod_q_mask = this->q - 1; + indices_len_t len; + int i; + + /* form polynomial F or F1 */ + memset(array, 0x00, this->N * sizeof(uint16_t)); + bi = this->indices; + len = this->indices_len[0]; + for (i = 0; i < len.p + len.m; i++) + { + array[bi[i]] = (i < len.p) ? 1 : mod_q_mask; + } + + if (this->num_polynomials == 3) + { + /* allocate temporary array t */ + t = malloc(this->N * sizeof(uint16_t)); + + /* form F1 * F2 */ + bi += len.p + len.m; + len = this->indices_len[1]; + ring_mult_i(array, len, bi, this->N, mod_q_mask, t, array); + + /* form (F1 * F2) + F3 */ + bi += len.p + len.m; + len = this->indices_len[2]; + for (i = 0; i < len.p + len.m; i++) + { + if (i < len.p) + { + array[bi[i]] += 1; + } + else + { + array[bi[i]] -= 1; + } + array[bi[i]] &= mod_q_mask; + } + free(t); + } +} + +METHOD(ntru_poly_t, ring_mult, void, + private_ntru_poly_t *this, uint16_t *a, uint16_t *c) +{ + uint16_t *t1, *t2; + uint16_t *bi = this->indices; + uint16_t mod_q_mask = this->q - 1; + int i; + + /* allocate temporary array t1 */ + t1 = malloc(this->N * sizeof(uint16_t)); + + if (this->num_polynomials == 1) + { + ring_mult_i(a, this->indices_len[0], bi, this->N, mod_q_mask, t1, c); + } + else + { + /* allocate temporary array t2 */ + t2 = malloc(this->N * sizeof(uint16_t)); + + /* t1 = a * b1 */ + ring_mult_i(a, this->indices_len[0], bi, this->N, mod_q_mask, t1, t1); + + /* t1 = (a * b1) * b2 */ + bi += this->indices_len[0].p + this->indices_len[0].m; + ring_mult_i(t1, this->indices_len[1], bi, this->N, mod_q_mask, t2, t1); + + /* t2 = a * b3 */ + bi += this->indices_len[1].p + this->indices_len[1].m; + ring_mult_i(a, this->indices_len[2], bi, this->N, mod_q_mask, t2, t2); + + /* c = (a * b1 * b2) + (a * b3) */ + for (i = 0; i < this->N; i++) + { + c[i] = (t1[i] + t2[i]) & mod_q_mask; + } + free(t2); + } + free(t1); +} + +METHOD(ntru_poly_t, destroy, void, + private_ntru_poly_t *this) +{ + memwipe(this->indices, sizeof(uint16_t) * get_size(this)); + free(this->indices); + free(this); +} + +static void init_indices(private_ntru_poly_t *this, bool is_product_form, + uint32_t indices_len_p, uint32_t indices_len_m) +{ + int n; + + if (is_product_form) + { + this->num_polynomials = 3; + for (n = 0; n < 3; n++) + { + this->indices_len[n].p = 0xff & indices_len_p; + this->indices_len[n].m = 0xff & indices_len_m; + this->num_indices += this->indices_len[n].p + + this->indices_len[n].m; + indices_len_p >>= 8; + indices_len_m >>= 8; + } + } + else + { + this->num_polynomials = 1; + this->indices_len[0].p = indices_len_p; + this->indices_len[0].m = indices_len_m; + this->num_indices = indices_len_p + indices_len_m; + } + this->indices = malloc(sizeof(uint16_t) * this->num_indices); +} + +/* + * Described in header. + */ +ntru_poly_t *ntru_poly_create_from_seed(hash_algorithm_t alg, chunk_t seed, + uint8_t c_bits, uint16_t N, uint16_t q, + uint32_t indices_len_p, + uint32_t indices_len_m, + bool is_product_form) +{ + private_ntru_poly_t *this; + size_t hash_len, octet_count = 0, i; + uint8_t octets[HASH_SIZE_SHA512], *used, num_left = 0, num_needed; + uint16_t index, limit, left = 0; + int n, num_indices, index_i = 0; + ntru_mgf1_t *mgf1; + + DBG2(DBG_LIB, "MGF1 is seeded with %u bytes", seed.len); + mgf1 = ntru_mgf1_create(alg, seed, TRUE); + if (!mgf1) + { + return NULL; + } + i = hash_len = mgf1->get_hash_size(mgf1); + + INIT(this, + .public = { + .get_size = _get_size, + .get_indices = _get_indices, + .get_array = _get_array, + .ring_mult = _ring_mult, + .destroy = _destroy, + }, + .N = N, + .q = q, + ); + + init_indices(this, is_product_form, indices_len_p, indices_len_m); + used = malloc(N); + limit = N * ((1 << c_bits) / N); + + /* generate indices for all polynomials */ + for (n = 0; n < this->num_polynomials; n++) + { + memset(used, 0, N); + num_indices = this->indices_len[n].p + this->indices_len[n].m; + + /* generate indices for a single polynomial */ + while (num_indices) + { + /* generate a random candidate index with a size of c_bits */ + do + { + /* use any leftover bits first */ + index = num_left ? left << (c_bits - num_left) : 0; + + /* get the rest of the bits needed from new octets */ + num_needed = c_bits - num_left; + + while (num_needed) + { + if (i == hash_len) + { + /* get another block from MGF1 */ + if (!mgf1->get_mask(mgf1, hash_len, octets)) + { + mgf1->destroy(mgf1); + destroy(this); + free(used); + return NULL; + } + octet_count += hash_len; + i = 0; + } + left = octets[i++]; + + if (num_needed <= 8) + { + /* all bits needed to fill the index are in this octet */ + index |= left >> (8 - num_needed); + num_left = 8 - num_needed; + num_needed = 0; + left &= 0xff >> (8 - num_left); + } + else + { + /* more than one octet will be needed */ + index |= left << (num_needed - 8); + num_needed -= 8; + } + } + } + while (index >= limit); + + /* form index and check if unique */ + index %= N; + if (!used[index]) + { + used[index] = 1; + this->indices[index_i++] = index; + num_indices--; + } + } + } + + DBG2(DBG_LIB, "MGF1 generates %u octets to derive %u indices", + octet_count, this->num_indices); + mgf1->destroy(mgf1); + free(used); + + return &this->public; +} + +/* + * Described in header. + */ +ntru_poly_t *ntru_poly_create_from_data(uint16_t *data, uint16_t N, uint16_t q, + uint32_t indices_len_p, + uint32_t indices_len_m, + bool is_product_form) +{ + private_ntru_poly_t *this; + int i; + + INIT(this, + .public = { + .get_size = _get_size, + .get_indices = _get_indices, + .get_array = _get_array, + .ring_mult = _ring_mult, + .destroy = _destroy, + }, + .N = N, + .q = q, + ); + + init_indices(this, is_product_form, indices_len_p, indices_len_m); + for (i = 0; i < this->num_indices; i++) + { + this->indices[i] = data[i]; + } + + return &this->public; +} + +EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_poly_create_from_seed); + +EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_poly_create_from_data); diff --git a/src/libstrongswan/plugins/ntru/ntru_poly.h b/src/libstrongswan/plugins/ntru/ntru_poly.h new file mode 100644 index 000000000..87c77103c --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_poly.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2014 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_poly ntru_poly + * @{ @ingroup ntru_p + */ + +#ifndef NTRU_POLY_H_ +#define NTRU_POLY_H_ + +typedef struct ntru_poly_t ntru_poly_t; + +#include <library.h> + +/** + * Implements a trinary polynomial storing the indices of non-zero coefficients + */ +struct ntru_poly_t { + + /** + * Get the size of the indices array + * + * @return number of indices + */ + size_t (*get_size)(ntru_poly_t *this); + + /** + * @return array containing the indices of the non-zero coefficients + */ + uint16_t* (*get_indices)(ntru_poly_t *this); + + /** + * @param array array containing all N coefficients of the polynomial + */ + void (*get_array)(ntru_poly_t *this, uint16_t *array); + + /** + * Multiply polynomial a with ntru_poly_t object b having sparse coeffients + * to form result polynomial c = a * b + * + * @param a input polynomial a + * @param b output polynomial c + */ + void (*ring_mult)(ntru_poly_t *this, uint16_t *a, uint16_t *c); + + /** + * Destroy ntru_poly_t object + */ + void (*destroy)(ntru_poly_t *this); +}; + +/** + * Create a trits polynomial from a seed using MGF1 with a base hash function + * + * @param alg hash algorithm to be used by MGF1 + * @param seed seed used by MGF1 to generate trits from + * @param N ring dimension, number of polynomial coefficients + * @param q large modulus + * @param c_bits number of bits for candidate index + * @param indices_len_p number of indices for +1 coefficients + * @param indices_len_m number of indices for -1 coefficients + * @param is_product_form generate multiple polynomials + */ +ntru_poly_t *ntru_poly_create_from_seed(hash_algorithm_t alg, chunk_t seed, + uint8_t c_bits, uint16_t N, uint16_t q, + uint32_t indices_len_p, + uint32_t indices_len_m, + bool is_product_form); + +/** + * Create a trits polynomial from an array of indices of non-zero coefficients + * + * @param data array of indices of non-zero coefficients + * @param N ring dimension, number of polynomial coefficients + * @param q large modulus + * @param indices_len_p number of indices for +1 coefficients + * @param indices_len_m number of indices for -1 coefficients + * @param is_product_form generate multiple polynomials + */ +ntru_poly_t *ntru_poly_create_from_data(uint16_t *data, uint16_t N, uint16_t q, + uint32_t indices_len_p, + uint32_t indices_len_m, + bool is_product_form); + +#endif /** NTRU_POLY_H_ @}*/ + diff --git a/src/libstrongswan/plugins/ntru/ntru_trits.c b/src/libstrongswan/plugins/ntru/ntru_trits.c new file mode 100644 index 000000000..f82501629 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_trits.c @@ -0,0 +1,133 @@ +/* + * 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_trits.h" +#include "ntru_mgf1.h" + +#include "ntru_crypto/ntru_crypto_ntru_convert.h" + +#include <utils/debug.h> +#include <utils/test.h> + +typedef struct private_ntru_trits_t private_ntru_trits_t; + +/** + * Private data of an ntru_trits_t object. + */ +struct private_ntru_trits_t { + + /** + * Public ntru_trits_t interface. + */ + ntru_trits_t public; + + /** + * Size of the trits array + */ + size_t trits_len; + + /** + * Array containing a trit per octet + */ + uint8_t *trits; + +}; + +METHOD(ntru_trits_t, get_size, size_t, + private_ntru_trits_t *this) +{ + return this->trits_len; +} + +METHOD(ntru_trits_t, get_trits, uint8_t*, + private_ntru_trits_t *this) +{ + return this->trits; +} + +METHOD(ntru_trits_t, destroy, void, + private_ntru_trits_t *this) +{ + memwipe(this->trits, this->trits_len); + free(this->trits); + free(this); +} + +/* + * Described in header. + */ +ntru_trits_t *ntru_trits_create(size_t len, hash_algorithm_t alg, chunk_t seed) +{ + private_ntru_trits_t *this; + uint8_t octets[HASH_SIZE_SHA512], buf[5], *trits; + size_t hash_len, octet_count = 0, trits_needed, i; + ntru_mgf1_t *mgf1; + + DBG2(DBG_LIB, "MGF1 is seeded with %u bytes", seed.len); + mgf1 = ntru_mgf1_create(alg, seed, TRUE); + if (!mgf1) + { + return NULL; + } + i = hash_len = mgf1->get_hash_size(mgf1); + + INIT(this, + .public = { + .get_size = _get_size, + .get_trits = _get_trits, + .destroy = _destroy, + }, + .trits_len = len, + .trits = malloc(len), + ); + + trits = this->trits; + trits_needed = this->trits_len; + + while (trits_needed > 0) + { + if (i == hash_len) + { + /* get another block from MGF1 */ + if (!mgf1->get_mask(mgf1, hash_len, octets)) + { + mgf1->destroy(mgf1); + destroy(this); + return NULL; + } + octet_count += hash_len; + i = 0; + } + if (octets[i] < 243) /* 243 = 3^5 */ + { + ntru_octet_2_trits(octets[i], (trits_needed < 5) ? buf : trits); + if (trits_needed < 5) + { + memcpy(trits, buf, trits_needed); + break; + } + trits += 5; + trits_needed -= 5; + } + i++; + } + DBG2(DBG_LIB, "MGF1 generates %u octets to extract %u trits", + octet_count, len); + mgf1->destroy(mgf1); + + return &this->public; +} + +EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_trits_create); diff --git a/src/libstrongswan/plugins/ntru/ntru_trits.h b/src/libstrongswan/plugins/ntru/ntru_trits.h new file mode 100644 index 000000000..524c51bac --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_trits.h @@ -0,0 +1,61 @@ +/* + * 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_trits ntru_trits + * @{ @ingroup ntru_p + */ + +#ifndef NTRU_TRITS_H_ +#define NTRU_TRITS_H_ + +typedef struct ntru_trits_t ntru_trits_t; + +#include <library.h> + +/** + * Implements an array of trinary elements (trits) + */ +struct ntru_trits_t { + + /** + * Get the size of the trits array + * + * @return number of trinary elements + */ + size_t (*get_size)(ntru_trits_t *this); + + /** + * @return octet array containing a trit per octet + */ + uint8_t* (*get_trits)(ntru_trits_t *this); + + /** + * Destroy ntru_trits_t object + */ + void (*destroy)(ntru_trits_t *this); +}; + +/** + * Create a trits array from a seed using MGF1 with a base hash function + * + * @param size size of the trits array + * @param alg hash algorithm to be used by MGF1 + * @param seed seed used by MGF1 to generate trits from + */ +ntru_trits_t *ntru_trits_create(size_t size, hash_algorithm_t alg, chunk_t seed); + +#endif /** NTRU_TRITS_H_ @}*/ + |