diff options
Diffstat (limited to 'src/libstrongswan/plugins/openssl')
22 files changed, 4113 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am new file mode 100644 index 000000000..f331a78eb --- /dev/null +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-openssl.la + +libstrongswan_openssl_la_SOURCES = openssl_plugin.h openssl_plugin.c \ + openssl_util.c openssl_util.h \ + openssl_crypter.c openssl_crypter.h \ + openssl_hasher.c openssl_hasher.h \ + openssl_diffie_hellman.c openssl_diffie_hellman.h \ + openssl_rsa_private_key.c openssl_rsa_private_key.h \ + openssl_rsa_public_key.c openssl_rsa_public_key.h \ + openssl_ec_diffie_hellman.c openssl_ec_diffie_hellman.h \ + openssl_ec_private_key.c openssl_ec_private_key.h \ + openssl_ec_public_key.c openssl_ec_public_key.h + +libstrongswan_openssl_la_LDFLAGS = -module +libstrongswan_openssl_la_LIBADD = -lcrypto + diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in new file mode 100644 index 000000000..f83b0ce38 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -0,0 +1,518 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 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@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@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/openssl +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_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 = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_openssl_la_DEPENDENCIES = +am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \ + openssl_util.lo openssl_crypter.lo openssl_hasher.lo \ + openssl_diffie_hellman.lo openssl_rsa_private_key.lo \ + openssl_rsa_public_key.lo openssl_ec_diffie_hellman.lo \ + openssl_ec_private_key.lo openssl_ec_public_key.lo +libstrongswan_openssl_la_OBJECTS = \ + $(am_libstrongswan_openssl_la_OBJECTS) +libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_openssl_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_openssl_la_SOURCES) +DIST_SOURCES = $(libstrongswan_openssl_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +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_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-openssl.la +libstrongswan_openssl_la_SOURCES = openssl_plugin.h openssl_plugin.c \ + openssl_util.c openssl_util.h \ + openssl_crypter.c openssl_crypter.h \ + openssl_hasher.c openssl_hasher.h \ + openssl_diffie_hellman.c openssl_diffie_hellman.h \ + openssl_rsa_private_key.c openssl_rsa_private_key.h \ + openssl_rsa_public_key.c openssl_rsa_public_key.h \ + openssl_ec_diffie_hellman.c openssl_ec_diffie_hellman.h \ + openssl_ec_private_key.c openssl_ec_private_key.h \ + openssl_ec_public_key.c openssl_ec_public_key.h + +libstrongswan_openssl_la_LDFLAGS = -module +libstrongswan_openssl_la_LIBADD = -lcrypto +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 \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/openssl/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libstrongswan/plugins/openssl/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 +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-openssl.la: $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_DEPENDENCIES) + $(libstrongswan_openssl_la_LINK) -rpath $(plugindir) $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_crypter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_diffie_hellman.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_diffie_hellman.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_private_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_public_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hasher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_private_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_public_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_util.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +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 $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +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-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(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 all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags 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 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/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c new file mode 100644 index 000000000..e59c4d615 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_crypter.c 4020 2008-05-28 12:20:38Z andreas $ + */ + +#include "openssl_crypter.h" + +#include <openssl/evp.h> + +typedef struct private_openssl_crypter_t private_openssl_crypter_t; + +/** + * Private data of openssl_crypter_t + */ +struct private_openssl_crypter_t { + + /** + * Public part of this class. + */ + openssl_crypter_t public; + + /* + * the key + */ + chunk_t key; + + /* + * the cipher to use + */ + const EVP_CIPHER *cipher; +}; + +/** + * Mapping from the algorithms defined in IKEv2 to + * OpenSSL algorithm names and their key length + */ +typedef struct { + /** + * Identifier specified in IKEv2 + */ + int ikev2_id; + + /** + * Name of the algorithm, as used in OpenSSL + */ + char *name; + + /** + * Minimum valid key length in bytes + */ + size_t key_size_min; + + /** + * Maximum valid key length in bytes + */ + size_t key_size_max; +} openssl_algorithm_t; + +#define END_OF_LIST -1 + +/** + * Algorithms for encryption + */ +static openssl_algorithm_t encryption_algs[] = { +/* {ENCR_DES_IV64, "***", 0, 0}, */ + {ENCR_DES, "des", 8, 8}, /* 64 bits */ + {ENCR_3DES, "des3", 24, 24}, /* 192 bits */ + {ENCR_RC5, "rc5", 5, 255}, /* 40 to 2040 bits, RFC 2451 */ + {ENCR_IDEA, "idea", 16, 16}, /* 128 bits, RFC 2451 */ + {ENCR_CAST, "cast", 5, 16}, /* 40 to 128 bits, RFC 2451 */ + {ENCR_BLOWFISH, "blowfish", 5, 56}, /* 40 to 448 bits, RFC 2451 */ +/* {ENCR_3IDEA, "***", 0, 0}, */ +/* {ENCR_DES_IV32, "***", 0, 0}, */ +/* {ENCR_NULL, "***", 0, 0}, */ /* handled separately */ +/* {ENCR_AES_CBC, "***", 0, 0}, */ /* handled separately */ +/* {ENCR_AES_CTR, "***", 0, 0}, */ /* disabled in evp.h */ + {END_OF_LIST, NULL, 0, 0}, +}; + +/** + * Look up an OpenSSL algorithm name and validate its key size + */ +static char* lookup_algorithm(openssl_algorithm_t *openssl_algo, + u_int16_t ikev2_algo, size_t *key_size) +{ + while (openssl_algo->ikev2_id != END_OF_LIST) + { + if (ikev2_algo == openssl_algo->ikev2_id) + { + /* set the key size if it is not set */ + if (*key_size == 0 && + (openssl_algo->key_size_min == openssl_algo->key_size_max)) + { + *key_size = openssl_algo->key_size_min; + } + + /* validate key size */ + if (*key_size < openssl_algo->key_size_min || + *key_size > openssl_algo->key_size_max) + { + return NULL; + } + return openssl_algo->name; + } + openssl_algo++; + } + return NULL; +} + +static void crypt(private_openssl_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst, int enc) +{ + int len; + u_char *out; + + out = data.ptr; + if (dst) + { + *dst = chunk_alloc(data.len); + out = dst->ptr; + } + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, this->cipher, NULL, this->key.ptr, iv.ptr, enc); + EVP_CIPHER_CTX_set_padding(&ctx, 0); /* disable padding */ + EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len); + EVP_CipherFinal_ex(&ctx, out, &len); /* since padding is disabled this does nothing */ + EVP_CIPHER_CTX_cleanup(&ctx); +} + +/** + * Implementation of crypter_t.decrypt. + */ +static void decrypt(private_openssl_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst) +{ + crypt(this, data, iv, dst, 0); +} + + +/** + * Implementation of crypter_t.encrypt. + */ +static void encrypt (private_openssl_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst) +{ + crypt(this, data, iv, dst, 1); +} + +/** + * Implementation of crypter_t.get_block_size. + */ +static size_t get_block_size(private_openssl_crypter_t *this) +{ + return this->cipher->block_size; +} + +/** + * Implementation of crypter_t.get_key_size. + */ +static size_t get_key_size(private_openssl_crypter_t *this) +{ + return this->key.len; +} + +/** + * Implementation of crypter_t.set_key. + */ +static void set_key(private_openssl_crypter_t *this, chunk_t key) +{ + memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len)); +} + +/** + * Implementation of crypter_t.destroy. + */ +static void destroy (private_openssl_crypter_t *this) +{ + free(this->key.ptr); + free(this); +} + +/* + * Described in header + */ +openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, + size_t key_size) +{ + private_openssl_crypter_t *this; + + this = malloc_thing(private_openssl_crypter_t); + + switch (algo) + { + case ENCR_NULL: + this->cipher = EVP_enc_null(); + break; + case ENCR_AES_CBC: + switch (key_size) + { + case 16: /* AES 128 */ + this->cipher = EVP_get_cipherbyname("aes128"); + break; + case 24: /* AES-192 */ + this->cipher = EVP_get_cipherbyname("aes192"); + break; + case 32: /* AES-256 */ + this->cipher = EVP_get_cipherbyname("aes256"); + break; + default: + free(this); + return NULL; + } + break; + default: + { + char* name = lookup_algorithm(encryption_algs, algo, &key_size); + if (!name) + { + /* algo unavailable or key_size invalid */ + free(this); + return NULL; + } + this->cipher = EVP_get_cipherbyname(name); + break; + } + } + + if (!this->cipher) + { + /* OpenSSL does not support the requested algo */ + free(this); + return NULL; + } + + this->key = chunk_alloc(key_size); + + this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt; + this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt; + this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size; + this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size; + this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key; + this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy; + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.h b/src/libstrongswan/plugins/openssl/openssl_crypter.h new file mode 100644 index 000000000..f80d0dec6 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_crypter.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_crypter openssl_crypter + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_CRYPTER_H_ +#define OPENSSL_CRYPTER_H_ + +typedef struct openssl_crypter_t openssl_crypter_t; + +#include <crypto/crypters/crypter.h> + +/** + * Implementation of crypters using OpenSSL. + */ +struct openssl_crypter_t { + + /** + * The crypter_t interface. + */ + crypter_t crypter_interface; +}; + +/** + * Constructor to create openssl_crypter_t. + * + * @param algo algorithm to implement + * @param key_size key size in bytes + * @return openssl_crypter_t, NULL if not supported + */ +openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, + size_t key_size); + +#endif /* OPENSSL_CRYPTER_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c new file mode 100644 index 000000000..95c079b0b --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_diffie_hellman.c 3896 2008-04-29 15:42:34Z tobias $ + */ + +#include <openssl/dh.h> + +#include "openssl_diffie_hellman.h" + +#include <debug.h> + +typedef struct modulus_entry_t modulus_entry_t; + +/** + * Entry of the modulus list. + */ +struct modulus_entry_t { + /** + * Group number as it is defined in file transform_substructure.h. + */ + diffie_hellman_group_t group; + + /** + * Pointer to the function to get the modulus. + */ + BIGNUM *(*get_prime)(BIGNUM *bn); + + /* + * Generator value. + */ + u_int16_t generator; +}; + +/** + * All supported modulus values. + */ +static modulus_entry_t modulus_entries[] = { + {MODP_768_BIT, get_rfc2409_prime_768, 2}, + {MODP_1024_BIT, get_rfc2409_prime_1024, 2}, + {MODP_1536_BIT, get_rfc3526_prime_1536, 2}, + {MODP_2048_BIT, get_rfc3526_prime_2048, 2}, + {MODP_3072_BIT, get_rfc3526_prime_3072, 2}, + {MODP_4096_BIT, get_rfc3526_prime_4096, 2}, + {MODP_6144_BIT, get_rfc3526_prime_6144, 2}, + {MODP_8192_BIT, get_rfc3526_prime_8192, 2}, +}; + +typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t; + +/** + * Private data of an openssl_diffie_hellman_t object. + */ +struct private_openssl_diffie_hellman_t { + /** + * Public openssl_diffie_hellman_t interface. + */ + openssl_diffie_hellman_t public; + + /** + * Diffie Hellman group number. + */ + u_int16_t group; + + /** + * Diffie Hellman object + */ + DH *dh; + + /** + * Other public value + */ + BIGNUM *pub_key; + + /** + * Shared secret + */ + chunk_t shared_secret; + + /** + * True if shared secret is computed + */ + bool computed; +}; + +/** + * Convert a BIGNUM to a chunk + */ +static void bn2chunk(BIGNUM *bn, chunk_t *chunk) +{ + chunk->len = BN_num_bytes(bn); + chunk->ptr = malloc(chunk->len); + BN_bn2bin(bn, chunk->ptr); +} + +/** + * Implementation of openssl_diffie_hellman_t.set_other_public_value. + */ +static void set_other_public_value(private_openssl_diffie_hellman_t *this, chunk_t value) +{ + int len; + BN_bin2bn(value.ptr, value.len, this->pub_key); + + len = DH_size(this->dh); + chunk_free(&this->shared_secret); + this->shared_secret = chunk_alloc(len); + + if (DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh) < 0) { + DBG1("DH shared secret computation failed"); + return; + } + + this->computed = TRUE; +} + +/** + * Implementation of openssl_diffie_hellman_t.get_other_public_value. + */ +static status_t get_other_public_value(private_openssl_diffie_hellman_t *this, + chunk_t *value) +{ + if (!this->computed) + { + return FAILED; + } + bn2chunk(this->pub_key, value); + return SUCCESS; +} + +/** + * Implementation of openssl_diffie_hellman_t.get_my_public_value. + */ +static void get_my_public_value(private_openssl_diffie_hellman_t *this,chunk_t *value) +{ + bn2chunk(this->dh->pub_key, value); +} + +/** + * Implementation of openssl_diffie_hellman_t.get_shared_secret. + */ +static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, chunk_t *secret) +{ + if (!this->computed) + { + return FAILED; + } + *secret = chunk_clone(this->shared_secret); + return SUCCESS; +} + +/** + * Implementation of openssl_diffie_hellman_t.get_dh_group. + */ +static diffie_hellman_group_t get_dh_group(private_openssl_diffie_hellman_t *this) +{ + return this->group; +} + +/** + * Lookup the modulus in modulo table + */ +static status_t set_modulus(private_openssl_diffie_hellman_t *this) +{ + int i; + for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++) + { + if (modulus_entries[i].group == this->group) + { + this->dh->p = modulus_entries[i].get_prime(NULL); + this->dh->g = BN_new(); + BN_set_word(this->dh->g, modulus_entries[i].generator); + return SUCCESS; + } + } + return NOT_FOUND; +} + +/** + * Implementation of openssl_diffie_hellman_t.destroy. + */ +static void destroy(private_openssl_diffie_hellman_t *this) +{ + BN_clear_free(this->pub_key); + DH_free(this->dh); + chunk_free(&this->shared_secret); + free(this); +} + +/* + * Described in header. + */ +openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t group) +{ + private_openssl_diffie_hellman_t *this = malloc_thing(private_openssl_diffie_hellman_t); + + this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; + this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; + this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; + this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; + this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; + this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; + + this->dh = DH_new(); + if (!this->dh) + { + free(this); + return NULL; + } + + this->group = group; + this->computed = FALSE; + + this->pub_key = BN_new(); + this->shared_secret = chunk_empty; + + /* find a modulus according to group */ + if (set_modulus(this) != SUCCESS) + { + destroy(this); + return NULL; + } + + /* generate my public and private values */ + if (!DH_generate_key(this->dh)) + { + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h new file mode 100644 index 000000000..c72b4aab0 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_diffie_hellman.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_diffie_hellman openssl_diffie_hellman + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_DIFFIE_HELLMAN_H_ +#define OPENSSL_DIFFIE_HELLMAN_H_ + +typedef struct openssl_diffie_hellman_t openssl_diffie_hellman_t; + +#include <library.h> + +/** + * Implementation of the Diffie-Hellman algorithm using OpenSSL. + */ +struct openssl_diffie_hellman_t { + + /** + * Implements diffie_hellman_t interface. + */ + diffie_hellman_t dh; +}; + +/** + * Creates a new openssl_diffie_hellman_t object. + * + * @param group Diffie Hellman group number to use + * @return openssl_diffie_hellman_t object, NULL if not supported + */ +openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t group); + +#endif /*OPENSSL_DIFFIE_HELLMAN_H_ @}*/ + diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c new file mode 100644 index 000000000..9d2bd44cd --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_ec_diffie_hellman.c 4052 2008-06-10 09:19:18Z tobias $ + */ + +#include <openssl/ec.h> +#include <openssl/objects.h> + +#include "openssl_ec_diffie_hellman.h" +#include "openssl_util.h" + +#include <debug.h> + +typedef struct private_openssl_ec_diffie_hellman_t private_openssl_ec_diffie_hellman_t; + +/** + * Private data of an openssl_ec_diffie_hellman_t object. + */ +struct private_openssl_ec_diffie_hellman_t { + /** + * Public openssl_ec_diffie_hellman_t interface. + */ + openssl_ec_diffie_hellman_t public; + + /** + * Diffie Hellman group number. + */ + u_int16_t group; + + /** + * EC private (public) key + */ + EC_KEY *key; + + /** + * EC group + */ + const EC_GROUP *ec_group; + + /** + * Other public key + */ + EC_POINT *pub_key; + + /** + * Shared secret + */ + chunk_t shared_secret; + + /** + * True if shared secret is computed + */ + bool computed; +}; + +/** + * Convert a chunk to an EC_POINT (which must already exist). The x and y + * coordinates of the point have to be concatenated in the chunk. + */ +static bool chunk2ecp(const EC_GROUP *group, chunk_t chunk, EC_POINT *point) +{ + BN_CTX *ctx; + BIGNUM *x, *y; + bool ret = FALSE; + + ctx = BN_CTX_new(); + if (!ctx) + { + return FALSE; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (!x || !y) + { + goto error; + } + + if (!openssl_bn_split(chunk, x, y)) + { + goto error; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) + { + goto error; + } + + ret = TRUE; +error: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +/** + * Convert an EC_POINT to a chunk by concatenating the x and y coordinates of + * the point. This function allocates memory for the chunk. + */ +static bool ecp2chunk(const EC_GROUP *group, const EC_POINT *point, chunk_t *chunk) +{ + BN_CTX *ctx; + BIGNUM *x, *y; + bool ret = FALSE; + + ctx = BN_CTX_new(); + if (!ctx) + { + return FALSE; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (!x || !y) + { + goto error; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) + { + goto error; + } + + if (!openssl_bn_cat(EC_FIELD_ELEMENT_LEN(group), x, y, chunk)) + { + goto error; + } + + ret = TRUE; +error: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +/** + * Compute the shared secret. + * + * We cannot use the function ECDH_compute_key() because that returns only the + * x coordinate of the shared secret point (which is defined, for instance, in + * 'NIST SP 800-56A'). + * However, we need both coordinates as RFC 4753 says: "The Diffie-Hellman + * public value is obtained by concatenating the x and y values. The format + * of the Diffie-Hellman shared secret value is the same as that of the + * Diffie-Hellman public value." + */ +static bool compute_shared_key(private_openssl_ec_diffie_hellman_t *this, chunk_t *shared_secret) +{ + const BIGNUM *priv_key; + EC_POINT *secret = NULL; + bool ret = FALSE; + + priv_key = EC_KEY_get0_private_key(this->key); + if (!priv_key) + { + goto error; + } + + secret = EC_POINT_new(this->ec_group); + if (!secret) + { + goto error; + } + + if (!EC_POINT_mul(this->ec_group, secret, NULL, this->pub_key, priv_key, NULL)) + { + goto error; + } + + if (!ecp2chunk(this->ec_group, secret, shared_secret)) + { + goto error; + } + + ret = TRUE; +error: + if (secret) + { + EC_POINT_clear_free(secret); + } + return ret; +} + +/** + * Implementation of openssl_ec_diffie_hellman_t.set_other_public_value. + */ +static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, chunk_t value) +{ + if (!chunk2ecp(this->ec_group, value, this->pub_key)) + { + DBG1("ECDH public value is malformed"); + return; + } + + chunk_free(&this->shared_secret); + + if (!compute_shared_key(this, &this->shared_secret)) { + DBG1("ECDH shared secret computation failed"); + return; + } + + this->computed = TRUE; +} + +/** + * Implementation of openssl_ec_diffie_hellman_t.get_other_public_value. + */ +static status_t get_other_public_value(private_openssl_ec_diffie_hellman_t *this, + chunk_t *value) +{ + if (!this->computed) + { + return FAILED; + } + + if (!ecp2chunk(this->ec_group, this->pub_key, value)) + { + return FAILED; + } + return SUCCESS; +} + +/** + * Implementation of openssl_ec_diffie_hellman_t.get_my_public_value. + */ +static void get_my_public_value(private_openssl_ec_diffie_hellman_t *this,chunk_t *value) +{ + ecp2chunk(this->ec_group, EC_KEY_get0_public_key(this->key), value); +} + +/** + * Implementation of openssl_ec_diffie_hellman_t.get_shared_secret. + */ +static status_t get_shared_secret(private_openssl_ec_diffie_hellman_t *this, chunk_t *secret) +{ + if (!this->computed) + { + return FAILED; + } + *secret = chunk_clone(this->shared_secret); + return SUCCESS; +} + +/** + * Implementation of openssl_ec_diffie_hellman_t.get_dh_group. + */ +static diffie_hellman_group_t get_dh_group(private_openssl_ec_diffie_hellman_t *this) +{ + return this->group; +} + +/** + * Implementation of openssl_ec_diffie_hellman_t.destroy. + */ +static void destroy(private_openssl_ec_diffie_hellman_t *this) +{ + EC_POINT_clear_free(this->pub_key); + EC_KEY_free(this->key); + chunk_free(&this->shared_secret); + free(this); +} + +/* + * Described in header. + */ +openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_group_t group) +{ + private_openssl_ec_diffie_hellman_t *this = malloc_thing(private_openssl_ec_diffie_hellman_t); + + this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; + this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; + this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; + this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; + this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; + this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; + + switch (group) + { + case ECP_192_BIT: + this->key = EC_KEY_new_by_curve_name(NID_X9_62_prime192v1); + break; + case ECP_224_BIT: + this->key = EC_KEY_new_by_curve_name(NID_secp224r1); + break; + case ECP_256_BIT: + this->key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + break; + case ECP_384_BIT: + this->key = EC_KEY_new_by_curve_name(NID_secp384r1); + break; + case ECP_521_BIT: + this->key = EC_KEY_new_by_curve_name(NID_secp521r1); + break; + default: + this->key = NULL; + break; + } + + if (!this->key) + { + free(this); + return NULL; + } + + /* caching the EC group */ + this->ec_group = EC_KEY_get0_group(this->key); + + this->pub_key = EC_POINT_new(this->ec_group); + if (!this->pub_key) + { + free(this); + return NULL; + } + + /* generate an EC private (public) key */ + if (!EC_KEY_generate_key(this->key)) + { + free(this); + return NULL; + } + + this->group = group; + this->computed = FALSE; + + this->shared_secret = chunk_empty; + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.h b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.h new file mode 100644 index 000000000..e89f1cbd7 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_ec_diffie_hellman.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_ec_diffie_hellman openssl_ec_diffie_hellman + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_EC_DIFFIE_HELLMAN_H_ +#define OPENSSL_EC_DIFFIE_HELLMAN_H_ + +typedef struct openssl_ec_diffie_hellman_t openssl_ec_diffie_hellman_t; + +#include <library.h> + +/** + * Implementation of the EC Diffie-Hellman algorithm using OpenSSL. + */ +struct openssl_ec_diffie_hellman_t { + + /** + * Implements diffie_hellman_t interface. + */ + diffie_hellman_t dh; +}; + +/** + * Creates a new openssl_ec_diffie_hellman_t object. + * + * @param group EC Diffie Hellman group number to use + * @return openssl_ec_diffie_hellman_t object, NULL if not supported + */ +openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_group_t group); + +#endif /*OPENSSL_EC_DIFFIE_HELLMAN_H_ @}*/ + diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c new file mode 100644 index 000000000..9f7df4bca --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_ec_private_key.c 4051 2008-06-10 09:08:27Z tobias $ + */ + +#include "openssl_ec_private_key.h" +#include "openssl_ec_public_key.h" +#include "openssl_util.h" + +#include <debug.h> + +#include <openssl/evp.h> +#include <openssl/ecdsa.h> + +typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t; + +/** + * Private data of a openssl_ec_private_key_t object. + */ +struct private_openssl_ec_private_key_t { + /** + * Public interface for this signer. + */ + openssl_ec_private_key_t public; + + /** + * EC key object + */ + EC_KEY *ec; + + /** + * Keyid formed as a SHA-1 hash of a privateKey object + */ + identification_t* keyid; + + /** + * Keyid formed as a SHA-1 hash of a privateKeyInfo object + */ + identification_t* keyid_info; + + /** + * reference count + */ + refcount_t ref; +}; + +/** + * Mapping from the signature scheme defined in (RFC 4754) to the elliptic + * curve and the hash algorithm + */ +typedef struct { + /** + * Scheme specified in RFC 4754 + */ + int scheme; + + /** + * NID of the hash + */ + int hash; + + /** + * NID of the curve + */ + int curve; +} openssl_ecdsa_scheme_t; + +#define END_OF_LIST -1 + +/** + * Signature schemes + */ +static openssl_ecdsa_scheme_t ecdsa_schemes[] = { + {SIGN_ECDSA_256, NID_sha256, NID_X9_62_prime256v1}, + {SIGN_ECDSA_384, NID_sha384, NID_secp384r1}, + {SIGN_ECDSA_521, NID_sha512, NID_secp521r1}, + {END_OF_LIST, 0, 0}, +}; + +/** + * Look up the hash and curve of a signature scheme + */ +static bool lookup_scheme(int scheme, int *hash, int *curve) +{ + openssl_ecdsa_scheme_t *ecdsa_scheme = ecdsa_schemes; + while (ecdsa_scheme->scheme != END_OF_LIST) + { + if (scheme == ecdsa_scheme->scheme) + { + *hash = ecdsa_scheme->hash; + *curve = ecdsa_scheme->curve; + return TRUE; + } + ecdsa_scheme++; + } + return FALSE; +} + +/** + * shared functions, implemented in openssl_ec_public_key.c + */ +bool openssl_ec_public_key_build_id(EC_KEY *ec, identification_t **keyid, + identification_t **keyid_info); + +openssl_ec_public_key_t *openssl_ec_public_key_create_from_private_key(EC_KEY *ec); + + +/** + * Convert an ECDSA_SIG to a chunk by concatenating r and s. + * This function allocates memory for the chunk. + */ +static bool sig2chunk(const EC_GROUP *group, ECDSA_SIG *sig, chunk_t *chunk) +{ + return openssl_bn_cat(EC_FIELD_ELEMENT_LEN(group), sig->r, sig->s, chunk); +} + +/** + * Build the signature + */ +static bool build_signature(private_openssl_ec_private_key_t *this, + int hash_type, chunk_t data, chunk_t *signature) +{ + chunk_t hash = chunk_empty; + ECDSA_SIG *sig; + bool ret = FALSE; + + if (!openssl_hash_chunk(hash_type, data, &hash)) + { + return FALSE; + } + + sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec); + if (!sig) + { + goto error; + } + + if (!sig2chunk(EC_KEY_get0_group(this->ec), sig, signature)) + { + goto error; + } + + ret = TRUE; +error: + chunk_free(&hash); + if (sig) + { + ECDSA_SIG_free(sig); + } + return ret; +} + +/** + * Implementation of private_key_t.get_type. + */ +static key_type_t get_type(private_openssl_ec_private_key_t *this) +{ + return KEY_ECDSA; +} + +/** + * Implementation of private_key_t.sign. + */ +static bool sign(private_openssl_ec_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) +{ + EC_GROUP *req_group; + const EC_GROUP *my_group; + int hash, curve; + + if (!lookup_scheme(scheme, &hash, &curve)) + { + DBG1("signature scheme %N not supported in EC", + signature_scheme_names, scheme); + return FALSE; + } + + req_group = EC_GROUP_new_by_curve_name(curve); + if (!req_group) + { + DBG1("signature scheme %N not supported in EC (required curve not supported)", + signature_scheme_names, scheme); + return FALSE; + } + + my_group = EC_KEY_get0_group(this->ec); + if (EC_GROUP_cmp(my_group, req_group, NULL) != 0) + { + DBG1("signature scheme %N not supported by private key", + signature_scheme_names, scheme); + return FALSE; + } + + EC_GROUP_free(req_group); + + return build_signature(this, hash, data, signature); +} + +/** + * Implementation of private_key_t.destroy. + */ +static bool decrypt(private_openssl_ec_private_key_t *this, + chunk_t crypto, chunk_t *plain) +{ + DBG1("EC private key decryption not implemented"); + return FALSE; +} + +/** + * Implementation of private_key_t.get_keysize. + */ +static size_t get_keysize(private_openssl_ec_private_key_t *this) +{ + return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)); +} + +/** + * Implementation of private_key_t.get_id. + */ +static identification_t* get_id(private_openssl_ec_private_key_t *this, + id_type_t type) +{ + switch (type) + { + case ID_PUBKEY_INFO_SHA1: + return this->keyid_info; + case ID_PUBKEY_SHA1: + return this->keyid; + default: + return NULL; + } +} + +/** + * Implementation of private_key_t.get_public_key. + */ +static openssl_ec_public_key_t* get_public_key(private_openssl_ec_private_key_t *this) +{ + return openssl_ec_public_key_create_from_private_key(this->ec); +} + +/** + * Implementation of private_key_t.belongs_to. + */ +static bool belongs_to(private_openssl_ec_private_key_t *this, public_key_t *public) +{ + identification_t *keyid; + + if (public->get_type(public) != KEY_ECDSA) + { + return FALSE; + } + keyid = public->get_id(public, ID_PUBKEY_SHA1); + if (keyid && keyid->equals(keyid, this->keyid)) + { + return TRUE; + } + keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1); + if (keyid && keyid->equals(keyid, this->keyid_info)) + { + return TRUE; + } + return FALSE; +} + +/** + * Implementation of private_key_t.get_encoding. + */ +static chunk_t get_encoding(private_openssl_ec_private_key_t *this) +{ + chunk_t enc = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL)); + u_char *p = enc.ptr; + i2d_ECPrivateKey(this->ec, &p); + return enc; +} + +/** + * Implementation of private_key_t.get_ref. + */ +static private_openssl_ec_private_key_t* get_ref(private_openssl_ec_private_key_t *this) +{ + ref_get(&this->ref); + return this; + +} + +/** + * Implementation of private_key_t.destroy. + */ +static void destroy(private_openssl_ec_private_key_t *this) +{ + if (ref_put(&this->ref)) + { + if (this->ec) + { + EC_KEY_free(this->ec); + } + DESTROY_IF(this->keyid); + DESTROY_IF(this->keyid_info); + free(this); + } +} + +/** + * Internal generic constructor + */ +static private_openssl_ec_private_key_t *openssl_ec_private_key_create_empty(void) +{ + private_openssl_ec_private_key_t *this = malloc_thing(private_openssl_ec_private_key_t); + + this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type; + this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign; + this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt; + this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize; + this->public.interface.get_id = (identification_t* (*) (private_key_t *this,id_type_t))get_id; + this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key; + this->public.interface.belongs_to = (bool (*) (private_key_t *this, public_key_t *public))belongs_to; + this->public.interface.get_encoding = (chunk_t(*)(private_key_t*))get_encoding; + this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref; + this->public.interface.destroy = (void (*)(private_key_t *this))destroy; + + this->ec = NULL; + this->keyid = NULL; + this->keyid_info = NULL; + this->ref = 1; + + return this; +} + +/** + * load private key from an ASN1 encoded blob + */ +static openssl_ec_private_key_t *load(chunk_t blob) +{ + u_char *p = blob.ptr; + private_openssl_ec_private_key_t *this = openssl_ec_private_key_create_empty(); + + this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&p, blob.len); + + chunk_clear(&blob); + + if (!this->ec) + { + destroy(this); + return NULL; + } + + if (!openssl_ec_public_key_build_id(this->ec, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + + if (!EC_KEY_check_key(this->ec)) + { + destroy(this); + return NULL; + } + + return &this->public; +} + +typedef struct private_builder_t private_builder_t; +/** + * Builder implementation for key loading/generation + */ +struct private_builder_t { + /** implements the builder interface */ + builder_t public; + /** loaded/generated private key */ + openssl_ec_private_key_t *key; +}; + +/** + * Implementation of builder_t.build + */ +static openssl_ec_private_key_t *build(private_builder_t *this) +{ + openssl_ec_private_key_t *key = this->key; + + free(this); + return key; +} + +/** + * Implementation of builder_t.add + */ +static void add(private_builder_t *this, builder_part_t part, ...) +{ + va_list args; + + if (this->key) + { + DBG1("ignoring surplus build part %N", builder_part_names, part); + return; + } + + switch (part) + { + case BUILD_BLOB_ASN1_DER: + { + va_start(args, part); + this->key = load(va_arg(args, chunk_t)); + va_end(args); + break; + } + default: + DBG1("ignoring unsupported build part %N", builder_part_names, part); + break; + } +} + +/** + * Builder construction function + */ +builder_t *openssl_ec_private_key_builder(key_type_t type) +{ + private_builder_t *this; + + if (type != KEY_ECDSA) + { + return NULL; + } + + this = malloc_thing(private_builder_t); + + this->key = NULL; + this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; + this->public.build = (void*(*)(builder_t *this))build; + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h new file mode 100644 index 000000000..629fc9574 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_ec_private_key.h 4051 2008-06-10 09:08:27Z tobias $ + */ + +/** + * @defgroup openssl_ec_private_key openssl_ec_private_key + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_EC_PRIVATE_KEY_H_ +#define OPENSSL_EC_PRIVATE_KEY_H_ + +#include <credentials/keys/private_key.h> + +typedef struct openssl_ec_private_key_t openssl_ec_private_key_t; + +/** + * private_key_t implementation of ECDSA using OpenSSL. + */ +struct openssl_ec_private_key_t { + + /** + * Implements private_key_t interface + */ + private_key_t interface; +}; + +/** + * Create the builder for a private key. + * + * @param type type of the key, must be KEY_ECDSA + * @return builder instance + */ +builder_t *openssl_ec_private_key_builder(key_type_t type); + +#endif /*OPENSSL_EC_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c new file mode 100644 index 000000000..2056575ba --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_ec_public_key.c 4051 2008-06-10 09:08:27Z tobias $ + */ + +#include "openssl_ec_public_key.h" +#include "openssl_util.h" + +#include <debug.h> + +#include <openssl/evp.h> +#include <openssl/ecdsa.h> +#include <openssl/x509.h> + +typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t; + +/** + * Private data structure with signing context. + */ +struct private_openssl_ec_public_key_t { + /** + * Public interface for this signer. + */ + openssl_ec_public_key_t public; + + /** + * EC key object + */ + EC_KEY *ec; + + /** + * Keyid formed as a SHA-1 hash of a publicKeyInfo object + */ + identification_t *keyid_info; + + /** + * Keyid formed as a SHA-1 hash of a publicKey object + */ + identification_t *keyid; + + /** + * reference counter + */ + refcount_t ref; +}; + +/** + * Convert a chunk to an ECDSA_SIG (which must already exist). r and s + * of the signature have to be concatenated in the chunk. + */ +static bool chunk2sig(const EC_GROUP *group, chunk_t chunk, ECDSA_SIG *sig) +{ + return openssl_bn_split(chunk, sig->r, sig->s); +} + +/** + * Verification of a signature as in RFC 4754 + */ +static bool verify_signature(private_openssl_ec_public_key_t *this, + int hash_type, chunk_t data, chunk_t signature) +{ + chunk_t hash = chunk_empty; + ECDSA_SIG *sig; + bool valid = FALSE; + + if (!openssl_hash_chunk(hash_type, data, &hash)) + { + return FALSE; + } + + sig = ECDSA_SIG_new(); + if (!sig) + { + goto error; + } + + if (!chunk2sig(EC_KEY_get0_group(this->ec), signature, sig)) + { + goto error; + } + + valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1); + +error: + if (sig) + { + ECDSA_SIG_free(sig); + } + chunk_free(&hash); + return valid; +} + + +/** + * Verification of the default signature using SHA-1 + */ +static bool verify_default_signature(private_openssl_ec_public_key_t *this, + chunk_t data, chunk_t signature) +{ + bool valid = FALSE; + chunk_t hash = chunk_empty; + u_char *p; + ECDSA_SIG *sig; + + /* remove any preceding 0-bytes from signature */ + while (signature.len && *(signature.ptr) == 0x00) + { + signature.len -= 1; + signature.ptr++; + } + + p = signature.ptr; + sig = d2i_ECDSA_SIG(NULL, (const u_char**)&p, signature.len); + if (!sig) + { + return FALSE; + } + + if (!openssl_hash_chunk(NID_sha1, data, &hash)) + { + goto error; + } + + valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1); + +error: + if (sig) + { + ECDSA_SIG_free(sig); + } + chunk_free(&hash); + return valid; +} + +/** + * Implementation of public_key_t.get_type. + */ +static key_type_t get_type(private_openssl_ec_public_key_t *this) +{ + return KEY_ECDSA; +} + +/** + * Implementation of public_key_t.verify. + */ +static bool verify(private_openssl_ec_public_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t signature) +{ + switch (scheme) + { + case SIGN_ECDSA_WITH_SHA1: + return verify_default_signature(this, data, signature); + case SIGN_ECDSA_256: + return verify_signature(this, NID_sha256, data, signature); + case SIGN_ECDSA_384: + return verify_signature(this, NID_sha384, data, signature); + case SIGN_ECDSA_521: + return verify_signature(this, NID_sha512, data, signature); + default: + DBG1("signature scheme %N not supported in EC", + signature_scheme_names, scheme); + return FALSE; + } +} + +/** + * Implementation of public_key_t.get_keysize. + */ +static bool encrypt(private_openssl_ec_public_key_t *this, chunk_t crypto, chunk_t *plain) +{ + DBG1("EC public key encryption not implemented"); + return FALSE; +} + +/** + * Implementation of public_key_t.get_keysize. + */ +static size_t get_keysize(private_openssl_ec_public_key_t *this) +{ + return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)); +} + +/** + * Implementation of public_key_t.get_id. + */ +static identification_t *get_id(private_openssl_ec_public_key_t *this, + id_type_t type) +{ + switch (type) + { + case ID_PUBKEY_INFO_SHA1: + return this->keyid_info; + case ID_PUBKEY_SHA1: + return this->keyid; + default: + return NULL; + } +} + +/** + * Encodes the public key + */ +static chunk_t get_encoding_raw(EC_KEY *ec) +{ + /* since the points can be stored in three different forms this may not + * be correct for all cases */ + const EC_GROUP *group = EC_KEY_get0_group(ec); + const EC_POINT *pub = EC_KEY_get0_public_key(ec); + chunk_t enc = chunk_alloc(EC_POINT_point2oct(group, pub, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)); + EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED, + enc.ptr, enc.len, NULL); + return enc; +} + +/** + * Encodes the public key info (public key with ec parameters) + */ +static chunk_t get_encoding_full(EC_KEY *ec) +{ + chunk_t enc = chunk_alloc(i2d_EC_PUBKEY(ec, NULL)); + u_char *p = enc.ptr; + i2d_EC_PUBKEY(ec, &p); + return enc; +} + +/* + * Implementation of public_key_t.get_encoding. + */ +static chunk_t get_encoding(private_openssl_ec_public_key_t *this) +{ + return get_encoding_full(this->ec); +} + +/** + * Implementation of public_key_t.get_ref. + */ +static private_openssl_ec_public_key_t* get_ref(private_openssl_ec_public_key_t *this) +{ + ref_get(&this->ref); + return this; +} + +/** + * Implementation of openssl_ec_public_key.destroy. + */ +static void destroy(private_openssl_ec_public_key_t *this) +{ + if (ref_put(&this->ref)) + { + if (this->ec) + { + EC_KEY_free(this->ec); + } + DESTROY_IF(this->keyid); + DESTROY_IF(this->keyid_info); + free(this); + } +} + +/** + * Generic private constructor + */ +static private_openssl_ec_public_key_t *openssl_ec_public_key_create_empty() +{ + private_openssl_ec_public_key_t *this = malloc_thing(private_openssl_ec_public_key_t); + + this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type; + this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify; + this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt; + this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize; + this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id; + this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding; + this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref; + this->public.interface.destroy = (void (*)(public_key_t *this))destroy; + + this->ec = NULL; + this->keyid = NULL; + this->keyid_info = NULL; + this->ref = 1; + + return this; +} + +/** + * Build key identifier from the public key using SHA1 hashed publicKey(Info). + * Also used in openssl_ec_private_key.c. + */ +bool openssl_ec_public_key_build_id(EC_KEY *ec, identification_t **keyid, + identification_t **keyid_info) +{ + chunk_t publicKeyInfo, publicKey, hash; + hasher_t *hasher; + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1("SHA1 hash algorithm not supported, unable to use EC"); + return FALSE; + } + + publicKey = get_encoding_raw(ec); + + hasher->allocate_hash(hasher, publicKey, &hash); + *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash); + chunk_free(&hash); + + publicKeyInfo = get_encoding_full(ec); + + hasher->allocate_hash(hasher, publicKeyInfo, &hash); + *keyid_info = identification_create_from_encoding(ID_PUBKEY_INFO_SHA1, hash); + chunk_free(&hash); + + hasher->destroy(hasher); + chunk_free(&publicKeyInfo); + chunk_free(&publicKey); + + return TRUE; +} + +/** + * Create a public key from BIGNUM values, used in openssl_ec_private_key.c + */ +openssl_ec_public_key_t *openssl_ec_public_key_create_from_private_key(EC_KEY *ec) +{ + private_openssl_ec_public_key_t *this = openssl_ec_public_key_create_empty(); + + this->ec = EC_KEY_new(); + EC_KEY_set_public_key(this->ec, EC_KEY_get0_public_key(ec)); + + if (!openssl_ec_public_key_build_id(this->ec, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + return &this->public; +} + +/** + * Load a public key from an ASN1 encoded blob + */ +static openssl_ec_public_key_t *load(chunk_t blob) +{ + u_char *p = blob.ptr; + private_openssl_ec_public_key_t *this = openssl_ec_public_key_create_empty(); + + this->ec = d2i_EC_PUBKEY(NULL, (const u_char**)&p, blob.len); + + chunk_clear(&blob); + + if (!this->ec) + { + destroy(this); + return NULL; + } + + if (!openssl_ec_public_key_build_id(this->ec, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + return &this->public; +} + +typedef struct private_builder_t private_builder_t; +/** + * Builder implementation for key loading + */ +struct private_builder_t { + /** implements the builder interface */ + builder_t public; + /** loaded public key */ + openssl_ec_public_key_t *key; +}; + +/** + * Implementation of builder_t.build + */ +static openssl_ec_public_key_t *build(private_builder_t *this) +{ + openssl_ec_public_key_t *key = this->key; + + free(this); + return key; +} + +/** + * Implementation of builder_t.add + */ +static void add(private_builder_t *this, builder_part_t part, ...) +{ + va_list args; + + if (this->key) + { + DBG1("ignoring surplus build part %N", builder_part_names, part); + return; + } + + switch (part) + { + case BUILD_BLOB_ASN1_DER: + { + va_start(args, part); + this->key = load(va_arg(args, chunk_t)); + va_end(args); + break; + } + default: + DBG1("ignoring unsupported build part %N", builder_part_names, part); + break; + } +} + +/** + * Builder construction function + */ +builder_t *openssl_ec_public_key_builder(key_type_t type) +{ + private_builder_t *this; + + if (type != KEY_ECDSA) + { + return NULL; + } + + this = malloc_thing(private_builder_t); + + this->key = NULL; + this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; + this->public.build = (void*(*)(builder_t *this))build; + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h new file mode 100644 index 000000000..92684402c --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_ec_public_key.h 4051 2008-06-10 09:08:27Z tobias $ + */ + +/** + * @defgroup openssl_ec_public_key openssl_ec_public_key + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_EC_PUBLIC_KEY_H_ +#define OPENSSL_EC_PUBLIC_KEY_H_ + +typedef struct openssl_ec_public_key_t openssl_ec_public_key_t; + +#include <credentials/keys/public_key.h> + +/** + * public_key_t implementation of ECDSA using OpenSSL. + */ +struct openssl_ec_public_key_t { + + /** + * Implements the public_key_t interface + */ + public_key_t interface; +}; + +/** + * Create the builder for a public key. + * + * @param type type of the key, must be KEY_ECDSA + * @return builder instance + */ +builder_t *openssl_ec_public_key_builder(key_type_t type); + +#endif /*OPENSSL_EC_PUBLIC_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.c b/src/libstrongswan/plugins/openssl/openssl_hasher.c new file mode 100644 index 000000000..1275cdfb0 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_hasher.c 3898 2008-04-30 09:23:13Z tobias $ + */ + +#include "openssl_hasher.h" + +#include <openssl/evp.h> + +typedef struct private_openssl_hasher_t private_openssl_hasher_t; + +/** + * Private data of openssl_hasher_t + */ +struct private_openssl_hasher_t { + + /** + * Public part of this class. + */ + openssl_hasher_t public; + + /** + * the hasher to use + */ + const EVP_MD *hasher; + + /** + * the current digest context + */ + EVP_MD_CTX *ctx; +}; + +/** + * Mapping from the algorithms defined in IKEv2 to + * OpenSSL algorithm names + */ +typedef struct { + /** + * Identifier specified in IKEv2 + */ + int ikev2_id; + + /** + * Name of the algorithm, as used in OpenSSL + */ + char *name; +} openssl_algorithm_t; + +#define END_OF_LIST -1 + +/** + * Algorithms for integrity + */ +static openssl_algorithm_t integrity_algs[] = { + {HASH_MD2, "md2"}, + {HASH_MD5, "md5"}, + {HASH_SHA1, "sha1"}, + {HASH_SHA256, "sha256"}, + {HASH_SHA384, "sha384"}, + {HASH_SHA512, "sha512"}, + {END_OF_LIST, NULL}, +}; + +/** + * Look up an OpenSSL algorithm name + */ +static char* lookup_algorithm(openssl_algorithm_t *openssl_algo, + u_int16_t ikev2_algo) +{ + while (openssl_algo->ikev2_id != END_OF_LIST) + { + if (ikev2_algo == openssl_algo->ikev2_id) + { + return openssl_algo->name; + } + openssl_algo++; + } + return NULL; +} + +/** + * Implementation of hasher_t.get_hash_size. + */ +static size_t get_hash_size(private_openssl_hasher_t *this) +{ + return this->hasher->md_size; +} + +/** + * Implementation of hasher_t.reset. + */ +static void reset(private_openssl_hasher_t *this) +{ + EVP_DigestInit_ex(this->ctx, this->hasher, NULL); +} + +/** + * Implementation of hasher_t.get_hash. + */ +static void get_hash(private_openssl_hasher_t *this, chunk_t chunk, + u_int8_t *hash) +{ + EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len); + if (hash) + { + EVP_DigestFinal_ex(this->ctx, hash, NULL); + reset(this); + } +} + +/** + * Implementation of hasher_t.allocate_hash. + */ +static void allocate_hash(private_openssl_hasher_t *this, chunk_t chunk, + chunk_t *hash) +{ + if (hash) + { + *hash = chunk_alloc(get_hash_size(this)); + get_hash(this, chunk, hash->ptr); + } + else + { + get_hash(this, chunk, NULL); + } +} + +/** + * Implementation of hasher_t.destroy. + */ +static void destroy (private_openssl_hasher_t *this) +{ + EVP_MD_CTX_destroy(this->ctx); + free(this); +} + +/* + * Described in header + */ +openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) +{ + private_openssl_hasher_t *this; + + char* name = lookup_algorithm(integrity_algs, algo); + if (!name) + { + /* algo unavailable */ + return NULL; + } + + this = malloc_thing(private_openssl_hasher_t); + + this->hasher = EVP_get_digestbyname(name); + if (!this->hasher) + { + /* OpenSSL does not support the requested algo */ + free(this); + return NULL; + } + + this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash; + this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash; + this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size; + this->public.hasher_interface.reset = (void (*) (hasher_t*))reset; + this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy; + + this->ctx = EVP_MD_CTX_create(); + + /* initialization */ + reset(this); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.h b/src/libstrongswan/plugins/openssl/openssl_hasher.h new file mode 100644 index 000000000..f776e9fd4 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_hasher.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_hasher openssl_hasher + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_HASHER_H_ +#define OPENSSL_HASHER_H_ + +typedef struct openssl_hasher_t openssl_hasher_t; + +#include <crypto/hashers/hasher.h> + +/** + * Implementation of hashers using OpenSSL. + */ +struct openssl_hasher_t { + + /** + * The hasher_t interface. + */ + hasher_t hasher_interface; +}; + +/** + * Constructor to create openssl_hasher_t. + * + * @param algo algorithm + * @param key_size key size in bytes + * @return openssl_hasher_t, NULL if not supported + */ +openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo); + +#endif /* OPENSSL_HASHER_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c new file mode 100644 index 000000000..7fdd7c224 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_plugin.c 4107 2008-06-25 12:39:32Z tobias $ + */ + +#include <openssl/evp.h> +#include <openssl/engine.h> + +#include "openssl_plugin.h" + +#include <library.h> +#include "openssl_crypter.h" +#include "openssl_hasher.h" +#include "openssl_diffie_hellman.h" +#include "openssl_ec_diffie_hellman.h" +#include "openssl_rsa_private_key.h" +#include "openssl_rsa_public_key.h" +#include "openssl_ec_private_key.h" +#include "openssl_ec_public_key.h" + +typedef struct private_openssl_plugin_t private_openssl_plugin_t; + +/** + * private data of openssl_plugin + */ +struct private_openssl_plugin_t { + + /** + * public functions + */ + openssl_plugin_t public; +}; + +/** + * Implementation of openssl_plugin_t.destroy + */ +static void destroy(private_openssl_plugin_t *this) +{ + lib->crypto->remove_crypter(lib->crypto, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->remove_hasher(lib->crypto, + (hasher_constructor_t)openssl_hasher_create); + lib->crypto->remove_dh(lib->crypto, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->remove_dh(lib->crypto, + (dh_constructor_t)openssl_ec_diffie_hellman_create); + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)openssl_rsa_private_key_builder); + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)openssl_rsa_public_key_builder); + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)openssl_ec_private_key_builder); + lib->creds->remove_builder(lib->creds, + (builder_constructor_t)openssl_ec_public_key_builder); + + ENGINE_cleanup(); + EVP_cleanup(); + + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_openssl_plugin_t *this = malloc_thing(private_openssl_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + OpenSSL_add_all_algorithms(); + + /* activate support for hardware accelerators */ + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); + + /* crypter */ + lib->crypto->add_crypter(lib->crypto, ENCR_DES, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_3DES, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_RC5, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_IDEA, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_CAST, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_NULL, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + (crypter_constructor_t)openssl_crypter_create); + + /* hasher */ + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + (hasher_constructor_t)openssl_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_MD2, + (hasher_constructor_t)openssl_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_MD5, + (hasher_constructor_t)openssl_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA256, + (hasher_constructor_t)openssl_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA384, + (hasher_constructor_t)openssl_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA512, + (hasher_constructor_t)openssl_hasher_create); + + /* diffie hellman */ + lib->crypto->add_dh(lib->crypto, MODP_768_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, + (dh_constructor_t)openssl_diffie_hellman_create); + + /* ec diffie hellman */ + lib->crypto->add_dh(lib->crypto, ECP_192_BIT, + (dh_constructor_t)openssl_ec_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, ECP_224_BIT, + (dh_constructor_t)openssl_ec_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, ECP_256_BIT, + (dh_constructor_t)openssl_ec_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, ECP_384_BIT, + (dh_constructor_t)openssl_ec_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, ECP_521_BIT, + (dh_constructor_t)openssl_ec_diffie_hellman_create); + + /* rsa */ + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + (builder_constructor_t)openssl_rsa_private_key_builder); + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + (builder_constructor_t)openssl_rsa_public_key_builder); + + /* ec */ + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, + (builder_constructor_t)openssl_ec_private_key_builder); + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, + (builder_constructor_t)openssl_ec_public_key_builder); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.h b/src/libstrongswan/plugins/openssl/openssl_plugin.h new file mode 100644 index 000000000..40f741dfa --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_plugin.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_p openssl + * @ingroup plugins + * + * @defgroup openssl_plugin openssl_plugin + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_PLUGIN_H_ +#define OPENSSL_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct openssl_plugin_t openssl_plugin_t; + +/** + * Plugin implementing crypto functions via the OpenSSL library + */ +struct openssl_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a openssl_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* OPENSSL_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c new file mode 100644 index 000000000..7595eed3a --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_rsa_private_key.c 3963 2008-05-15 12:41:06Z tobias $ + */ + +#include "openssl_rsa_private_key.h" +#include "openssl_rsa_public_key.h" + +#include <debug.h> + +#include <openssl/evp.h> +#include <openssl/rsa.h> + +/** + * Public exponent to use for key generation. + */ +#define PUBLIC_EXPONENT 0x10001 + +typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t; + +/** + * Private data of a openssl_rsa_private_key_t object. + */ +struct private_openssl_rsa_private_key_t { + /** + * Public interface for this signer. + */ + openssl_rsa_private_key_t public; + + /** + * RSA object from OpenSSL + */ + RSA *rsa; + + /** + * Keyid formed as a SHA-1 hash of a privateKey object + */ + identification_t* keyid; + + /** + * Keyid formed as a SHA-1 hash of a privateKeyInfo object + */ + identification_t* keyid_info; + + /** + * reference count + */ + refcount_t ref; +}; + +/** + * shared functions, implemented in openssl_rsa_public_key.c + */ +bool openssl_rsa_public_key_build_id(RSA *rsa, identification_t **keyid, + identification_t **keyid_info); + + +openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGNUM *e); + + +/** + * Build an EMPSA PKCS1 signature described in PKCS#1 + */ +static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, + int type, chunk_t data, chunk_t *signature) +{ + bool success = FALSE; + const EVP_MD *hasher = EVP_get_digestbynid(type); + if (!hasher) + { + return FALSE; + } + + EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + EVP_PKEY *key = EVP_PKEY_new(); + if (!ctx || !key) + { + goto error; + } + + if (!EVP_PKEY_set1_RSA(key, this->rsa)) + { + goto error; + } + + if (!EVP_SignInit_ex(ctx, hasher, NULL)) + { + goto error; + } + + if (!EVP_SignUpdate(ctx, data.ptr, data.len)) + { + goto error; + } + + *signature = chunk_alloc(RSA_size(this->rsa)); + + if (!EVP_SignFinal(ctx, signature->ptr, &signature->len, key)) + { + goto error; + } + + success = TRUE; + +error: + if (key) + { + EVP_PKEY_free(key); + } + if (ctx) + { + EVP_MD_CTX_destroy(ctx); + } + return success; +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static key_type_t get_type(private_openssl_rsa_private_key_t *this) +{ + return KEY_RSA; +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) +{ + switch (scheme) + { + case SIGN_DEFAULT: + /* default is EMSA-PKCS1 using SHA1 */ + case SIGN_RSA_EMSA_PKCS1_SHA1: + return build_emsa_pkcs1_signature(this, NID_sha1, data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA256: + return build_emsa_pkcs1_signature(this, NID_sha256, data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA384: + return build_emsa_pkcs1_signature(this, NID_sha384, data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA512: + return build_emsa_pkcs1_signature(this, NID_sha512, data, signature); + case SIGN_RSA_EMSA_PKCS1_MD5: + return build_emsa_pkcs1_signature(this, NID_md5, data, signature); + default: + DBG1("signature scheme %N not supported in RSA", + signature_scheme_names, scheme); + return FALSE; + } +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static bool decrypt(private_openssl_rsa_private_key_t *this, + chunk_t crypto, chunk_t *plain) +{ + DBG1("RSA private key decryption not implemented"); + return FALSE; +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static size_t get_keysize(private_openssl_rsa_private_key_t *this) +{ + return RSA_size(this->rsa); +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static identification_t* get_id(private_openssl_rsa_private_key_t *this, + id_type_t type) +{ + switch (type) + { + case ID_PUBKEY_INFO_SHA1: + return this->keyid_info; + case ID_PUBKEY_SHA1: + return this->keyid; + default: + return NULL; + } +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static openssl_rsa_public_key_t* get_public_key(private_openssl_rsa_private_key_t *this) +{ + return openssl_rsa_public_key_create_from_n_e(this->rsa->n, this->rsa->e); +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static bool belongs_to(private_openssl_rsa_private_key_t *this, public_key_t *public) +{ + identification_t *keyid; + + if (public->get_type(public) != KEY_RSA) + { + return FALSE; + } + keyid = public->get_id(public, ID_PUBKEY_SHA1); + if (keyid && keyid->equals(keyid, this->keyid)) + { + return TRUE; + } + keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1); + if (keyid && keyid->equals(keyid, this->keyid_info)) + { + return TRUE; + } + return FALSE; +} + +/** + * Implementation of private_key_t.get_encoding. + */ +static chunk_t get_encoding(private_openssl_rsa_private_key_t *this) +{ + chunk_t enc = chunk_alloc(i2d_RSAPrivateKey(this->rsa, NULL)); + u_char *p = enc.ptr; + i2d_RSAPrivateKey(this->rsa, &p); + return enc; +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static private_openssl_rsa_private_key_t* get_ref(private_openssl_rsa_private_key_t *this) +{ + ref_get(&this->ref); + return this; + +} + +/** + * Implementation of openssl_rsa_private_key.destroy. + */ +static void destroy(private_openssl_rsa_private_key_t *this) +{ + if (ref_put(&this->ref)) + { + if (this->rsa) + { + RSA_free(this->rsa); + } + DESTROY_IF(this->keyid); + DESTROY_IF(this->keyid_info); + free(this); + } +} + +/** + * Internal generic constructor + */ +static private_openssl_rsa_private_key_t *openssl_rsa_private_key_create_empty(void) +{ + private_openssl_rsa_private_key_t *this = malloc_thing(private_openssl_rsa_private_key_t); + + this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type; + this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign; + this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt; + this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize; + this->public.interface.get_id = (identification_t* (*) (private_key_t *this,id_type_t))get_id; + this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key; + this->public.interface.belongs_to = (bool (*) (private_key_t *this, public_key_t *public))belongs_to; + this->public.interface.get_encoding = (chunk_t(*)(private_key_t*))get_encoding; + this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref; + this->public.interface.destroy = (void (*)(private_key_t *this))destroy; + + this->keyid = NULL; + this->keyid_info = NULL; + this->ref = 1; + + return this; +} + +/** + * Generate an RSA key of specified key size + */ +static openssl_rsa_private_key_t *generate(size_t key_size) +{ + private_openssl_rsa_private_key_t *this = openssl_rsa_private_key_create_empty(); + + this->rsa = RSA_generate_key(key_size, PUBLIC_EXPONENT, NULL, NULL); + + if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + + return &this->public; +} + +/** + * load private key from an ASN1 encoded blob + */ +static openssl_rsa_private_key_t *load(chunk_t blob) +{ + u_char *p = blob.ptr; + private_openssl_rsa_private_key_t *this = openssl_rsa_private_key_create_empty(); + + this->rsa = d2i_RSAPrivateKey(NULL, (const u_char**)&p, blob.len); + + chunk_clear(&blob); + + if (!this->rsa) + { + destroy(this); + return NULL; + } + + if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + + if (!RSA_check_key(this->rsa)) + { + destroy(this); + return NULL; + } + + return &this->public; +} + +typedef struct private_builder_t private_builder_t; +/** + * Builder implementation for key loading/generation + */ +struct private_builder_t { + /** implements the builder interface */ + builder_t public; + /** loaded/generated private key */ + openssl_rsa_private_key_t *key; +}; + +/** + * Implementation of builder_t.build + */ +static openssl_rsa_private_key_t *build(private_builder_t *this) +{ + openssl_rsa_private_key_t *key = this->key; + + free(this); + return key; +} + +/** + * Implementation of builder_t.add + */ +static void add(private_builder_t *this, builder_part_t part, ...) +{ + va_list args; + + if (this->key) + { + DBG1("ignoring surplus build part %N", builder_part_names, part); + return; + } + + switch (part) + { + case BUILD_BLOB_ASN1_DER: + { + va_start(args, part); + this->key = load(va_arg(args, chunk_t)); + va_end(args); + break; + } + case BUILD_KEY_SIZE: + { + va_start(args, part); + this->key = generate(va_arg(args, u_int)); + va_end(args); + break; + } + default: + DBG1("ignoring unsupported build part %N", builder_part_names, part); + break; + } +} + +/** + * Builder construction function + */ +builder_t *openssl_rsa_private_key_builder(key_type_t type) +{ + private_builder_t *this; + + if (type != KEY_RSA) + { + return NULL; + } + + this = malloc_thing(private_builder_t); + + this->key = NULL; + this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; + this->public.build = (void*(*)(builder_t *this))build; + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h new file mode 100644 index 000000000..81d81b2db --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_rsa_private_key.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_rsa_private_key openssl_rsa_private_key + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_RSA_PRIVATE_KEY_H_ +#define OPENSSL_RSA_PRIVATE_KEY_H_ + +#include <credentials/keys/private_key.h> + +typedef struct openssl_rsa_private_key_t openssl_rsa_private_key_t; + +/** + * private_key_t implementation of RSA algorithm using OpenSSL. + */ +struct openssl_rsa_private_key_t { + + /** + * Implements private_key_t interface + */ + private_key_t interface; +}; + +/** + * Create the builder for a private key. + * + * @param type type of the key, must be KEY_RSA + * @return builder instance + */ +builder_t *openssl_rsa_private_key_builder(key_type_t type); + +#endif /*OPENSSL_RSA_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c new file mode 100644 index 000000000..755b86e96 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_rsa_public_key.c 3963 2008-05-15 12:41:06Z tobias $ + */ + +#include "openssl_rsa_public_key.h" + +#include <debug.h> + +#include <openssl/evp.h> +#include <openssl/rsa.h> +#include <openssl/x509.h> + +typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t; + +/** + * Private data structure with signing context. + */ +struct private_openssl_rsa_public_key_t { + /** + * Public interface for this signer. + */ + openssl_rsa_public_key_t public; + + /** + * RSA object from OpenSSL + */ + RSA *rsa; + + /** + * Keyid formed as a SHA-1 hash of a publicKeyInfo object + */ + identification_t *keyid_info; + + /** + * Keyid formed as a SHA-1 hash of a publicKey object + */ + identification_t *keyid; + + /** + * reference counter + */ + refcount_t ref; +}; + +/** + * Verification of an EMPSA PKCS1 signature described in PKCS#1 + */ +static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this, + int type, chunk_t data, chunk_t signature) +{ + bool valid = FALSE; + const EVP_MD *hasher = EVP_get_digestbynid(type); + if (!hasher) + { + return FALSE; + } + + EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + EVP_PKEY *key = EVP_PKEY_new(); + if (!ctx || !key) + { + goto error; + } + + if (!EVP_PKEY_set1_RSA(key, this->rsa)) + { + goto error; + } + + if (!EVP_VerifyInit_ex(ctx, hasher, NULL)) + { + goto error; + } + + if (!EVP_VerifyUpdate(ctx, data.ptr, data.len)) + { + goto error; + } + + /* remove any preceding 0-bytes from signature */ + while (signature.len && *(signature.ptr) == 0x00) + { + signature.len -= 1; + signature.ptr++; + } + + valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1); + +error: + if (key) + { + EVP_PKEY_free(key); + } + if (ctx) + { + EVP_MD_CTX_destroy(ctx); + } + return valid; +} + +/** + * Implementation of public_key_t.get_type. + */ +static key_type_t get_type(private_openssl_rsa_public_key_t *this) +{ + return KEY_RSA; +} + +/** + * Implementation of public_key_t.verify. + */ +static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t signature) +{ + switch (scheme) + { + case SIGN_DEFAULT: + /* default is EMSA-PKCS1 using SHA1 */ + case SIGN_RSA_EMSA_PKCS1_SHA1: + return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA256: + return verify_emsa_pkcs1_signature(this, NID_sha256, data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA384: + return verify_emsa_pkcs1_signature(this, NID_sha384, data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA512: + return verify_emsa_pkcs1_signature(this, NID_sha512, data, signature); + case SIGN_RSA_EMSA_PKCS1_MD5: + return verify_emsa_pkcs1_signature(this, NID_md5, data, signature); + default: + DBG1("signature scheme %N not supported in RSA", + signature_scheme_names, scheme); + return FALSE; + } +} + +/** + * Implementation of public_key_t.get_keysize. + */ +static bool encrypt(private_openssl_rsa_public_key_t *this, chunk_t crypto, chunk_t *plain) +{ + DBG1("RSA public key encryption not implemented"); + return FALSE; +} + +/** + * Implementation of public_key_t.get_keysize. + */ +static size_t get_keysize(private_openssl_rsa_public_key_t *this) +{ + return RSA_size(this->rsa); +} + +/** + * Implementation of public_key_t.get_id. + */ +static identification_t *get_id(private_openssl_rsa_public_key_t *this, + id_type_t type) +{ + switch (type) + { + case ID_PUBKEY_INFO_SHA1: + return this->keyid_info; + case ID_PUBKEY_SHA1: + return this->keyid; + default: + return NULL; + } +} + +/** + * Encodes the public key + */ +static chunk_t get_encoding_raw(RSA *rsa) +{ + chunk_t enc = chunk_alloc(i2d_RSAPublicKey(rsa, NULL)); + u_char *p = enc.ptr; + i2d_RSAPublicKey(rsa, &p); + return enc; +} + +/** + * Encodes the public key with the algorithm used + */ +static chunk_t get_encoding_with_algo(RSA *rsa) +{ + u_char *p; + chunk_t enc; + X509_PUBKEY *pubkey = X509_PUBKEY_new(); + + ASN1_OBJECT_free(pubkey->algor->algorithm); + pubkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption); + + if (pubkey->algor->parameter == NULL || + pubkey->algor->parameter->type != V_ASN1_NULL) + { + ASN1_TYPE_free(pubkey->algor->parameter); + pubkey->algor->parameter = ASN1_TYPE_new(); + pubkey->algor->parameter->type = V_ASN1_NULL; + } + + enc = get_encoding_raw(rsa); + M_ASN1_BIT_STRING_set(pubkey->public_key, enc.ptr, enc.len); + chunk_free(&enc); + + enc = chunk_alloc(i2d_X509_PUBKEY(pubkey, NULL)); + p = enc.ptr; + i2d_X509_PUBKEY(pubkey, &p); + X509_PUBKEY_free(pubkey); + return enc; +} + +/* + * Implementation of public_key_t.get_encoding. + */ +static chunk_t get_encoding(private_openssl_rsa_public_key_t *this) +{ + return get_encoding_raw(this->rsa); +} + +/** + * Implementation of public_key_t.get_ref. + */ +static private_openssl_rsa_public_key_t* get_ref(private_openssl_rsa_public_key_t *this) +{ + ref_get(&this->ref); + return this; +} + +/** + * Implementation of openssl_rsa_public_key.destroy. + */ +static void destroy(private_openssl_rsa_public_key_t *this) +{ + if (ref_put(&this->ref)) + { + if (this->rsa) + { + RSA_free(this->rsa); + } + DESTROY_IF(this->keyid); + DESTROY_IF(this->keyid_info); + free(this); + } +} + +/** + * Generic private constructor + */ +static private_openssl_rsa_public_key_t *openssl_rsa_public_key_create_empty() +{ + private_openssl_rsa_public_key_t *this = malloc_thing(private_openssl_rsa_public_key_t); + + this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type; + this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify; + this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt; + this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize; + this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id; + this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding; + this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref; + this->public.interface.destroy = (void (*)(public_key_t *this))destroy; + + this->keyid = NULL; + this->keyid_info = NULL; + this->ref = 1; + + return this; +} + +/** + * Build the RSA key identifier from n and e using SHA1 hashed publicKey(Info). + * Also used in openssl_rsa_private_key.c. + */ +bool openssl_rsa_public_key_build_id(RSA *rsa, identification_t **keyid, + identification_t **keyid_info) +{ + chunk_t publicKeyInfo, publicKey, hash; + hasher_t *hasher; + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1("SHA1 hash algorithm not supported, unable to use RSA"); + return FALSE; + } + + publicKey = get_encoding_raw(rsa); + + hasher->allocate_hash(hasher, publicKey, &hash); + *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash); + chunk_free(&hash); + + publicKeyInfo = get_encoding_with_algo(rsa); + + hasher->allocate_hash(hasher, publicKeyInfo, &hash); + *keyid_info = identification_create_from_encoding(ID_PUBKEY_INFO_SHA1, hash); + chunk_free(&hash); + + hasher->destroy(hasher); + chunk_free(&publicKeyInfo); + chunk_free(&publicKey); + + return TRUE; +} + +/** + * Create a public key from BIGNUM values, used in openssl_rsa_private_key.c + */ +openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGNUM *e) +{ + private_openssl_rsa_public_key_t *this = openssl_rsa_public_key_create_empty(); + + this->rsa = RSA_new(); + this->rsa->n = BN_dup(n); + this->rsa->e = BN_dup(e); + + if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + return &this->public; +} + +/** + * Load a public key from an ASN1 encoded blob + */ +static openssl_rsa_public_key_t *load(chunk_t blob) +{ + u_char *p = blob.ptr; + private_openssl_rsa_public_key_t *this = openssl_rsa_public_key_create_empty(); + + this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&p, blob.len); + + chunk_clear(&blob); + + if (!this->rsa) + { + destroy(this); + return NULL; + } + + if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info)) + { + destroy(this); + return NULL; + } + return &this->public; +} + +typedef struct private_builder_t private_builder_t; +/** + * Builder implementation for key loading + */ +struct private_builder_t { + /** implements the builder interface */ + builder_t public; + /** loaded public key */ + openssl_rsa_public_key_t *key; +}; + +/** + * Implementation of builder_t.build + */ +static openssl_rsa_public_key_t *build(private_builder_t *this) +{ + openssl_rsa_public_key_t *key = this->key; + + free(this); + return key; +} + +/** + * Implementation of builder_t.add + */ +static void add(private_builder_t *this, builder_part_t part, ...) +{ + va_list args; + + if (this->key) + { + DBG1("ignoring surplus build part %N", builder_part_names, part); + return; + } + + switch (part) + { + case BUILD_BLOB_ASN1_DER: + { + va_start(args, part); + this->key = load(va_arg(args, chunk_t)); + va_end(args); + break; + } + default: + DBG1("ignoring unsupported build part %N", builder_part_names, part); + break; + } +} + +/** + * Builder construction function + */ +builder_t *openssl_rsa_public_key_builder(key_type_t type) +{ + private_builder_t *this; + + if (type != KEY_RSA) + { + return NULL; + } + + this = malloc_thing(private_builder_t); + + this->key = NULL; + this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; + this->public.build = (void*(*)(builder_t *this))build; + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h new file mode 100644 index 000000000..570fb69cb --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_rsa_public_key.h 4000 2008-05-22 12:13:10Z tobias $ + */ + +/** + * @defgroup openssl_rsa_public_key openssl_rsa_public_key + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_RSA_PUBLIC_KEY_H_ +#define OPENSSL_RSA_PUBLIC_KEY_H_ + +typedef struct openssl_rsa_public_key_t openssl_rsa_public_key_t; + +#include <credentials/keys/public_key.h> + +/** + * public_key_t implementation of RSA algorithm using OpenSSL. + */ +struct openssl_rsa_public_key_t { + + /** + * Implements the public_key_t interface + */ + public_key_t interface; +}; + +/** + * Create the builder for a public key. + * + * @param type type of the key, must be KEY_RSA + * @return builder instance + */ +builder_t *openssl_rsa_public_key_builder(key_type_t type); + +#endif /*OPENSSL_RSA_PUBLIC_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c new file mode 100644 index 000000000..3c4f6595b --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_util.c 4051 2008-06-10 09:08:27Z tobias $ + */ + +#include "openssl_util.h" + +#include <debug.h> + +#include <openssl/evp.h> + +/** + * Described in header. + */ +bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash) +{ + EVP_MD_CTX *ctx; + bool ret = FALSE; + const EVP_MD *hasher = EVP_get_digestbynid(hash_type); + if (!hasher) + { + return FALSE; + } + + ctx = EVP_MD_CTX_create(); + if (!ctx) + { + goto error; + } + + if (!EVP_DigestInit_ex(ctx, hasher, NULL)) + { + goto error; + } + + if (!EVP_DigestUpdate(ctx, data.ptr, data.len)) + { + goto error; + } + + *hash = chunk_alloc(hasher->md_size); + if (!EVP_DigestFinal_ex(ctx, hash->ptr, NULL)) + { + chunk_free(hash); + goto error; + } + + ret = TRUE; +error: + if (ctx) + { + EVP_MD_CTX_destroy(ctx); + } + return ret; +} + +/** + * Described in header. + */ +bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk) +{ + int offset; + + chunk->len = len * 2; + chunk->ptr = malloc(chunk->len); + memset(chunk->ptr, 0, chunk->len); + + offset = len - BN_num_bytes(a); + if (!BN_bn2bin(a, chunk->ptr + offset)) + { + goto error; + } + + offset = len - BN_num_bytes(b); + if (!BN_bn2bin(b, chunk->ptr + len + offset)) + { + goto error; + } + + return TRUE; +error: + chunk_free(chunk); + return FALSE; +} + + +/** + * Described in header. + */ +bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b) +{ + int len; + + if ((chunk.len % 2) != 0) + { + return FALSE; + } + + len = chunk.len / 2; + + if (!BN_bin2bn(chunk.ptr, len, a) || + !BN_bin2bn(chunk.ptr + len, len, b)) + { + return FALSE; + } + + return TRUE; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h new file mode 100644 index 000000000..2dbd5054e --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_util.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id: openssl_util.h 4051 2008-06-10 09:08:27Z tobias $ + */ + +/** + * @defgroup openssl_util openssl_util + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_UTIL_H_ +#define OPENSSL_UTIL_H_ + +#include <library.h> +#include <openssl/bn.h> + +/** + * Returns the length in bytes of a field element + */ +#define EC_FIELD_ELEMENT_LEN(group) ((EC_GROUP_get_degree(group) + 7) / 8) + +/** + * Creates a hash of a given type of a chunk of data. + * + * Note: this function allocates memory for the hash + * + * @param hash_type NID of the hash + * @param data the chunk of data to hash + * @param hash chunk that contains the hash + * @return TRUE on success, FALSE otherwise + */ +bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash); + +/** + * Concatenates two bignums into a chunk, thereby enfocing the length of + * a single BIGNUM, if necessary, by pre-pending it with zeros. + * + * Note: this function allocates memory for the chunk + * + * @param len the length of a single BIGNUM + * @param a first BIGNUM + * @param b second BIGNUM + * @param chunk resulting chunk + * @return TRUE on success, FALSE otherwise + */ +bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk); + +/** + * Splits a chunk into two bignums of equal binary length. + * + * @param chunk a chunk that contains the two BIGNUMs + * @param a first BIGNUM + * @param b second BIGNUM + * @return TRUE on success, FALSE otherwise + */ +bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b); + +#endif /*OPENSSL_UTIL_H_ @}*/ |